0

我用一些数据创建了一个 jtable。
但是由于大小限制,我只能看到单元格的部分数据。

如何使 jtable 单元格的整个数据在鼠标焦点上可见?

4

1 回答 1

2

为了使单元格可以越界显示,您需要实现 TableUI 类。

基本上你需要自己画细胞。代码有点长,但绝对适合我。

为了解决这个问题,创建一个新的 MyTableUI 类扩展 javax.swing.plaf.basic.BasicTableUI,覆盖它的 paint() 方法。

完整代码如下,您可以复制到您的 ide 并运行它。

package me.chenyi.table;

import javax.swing.*;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.*;
import java.awt.*;

public class MyBasicTableUI extends BasicTableUI
{
    @Override
    public void paint(Graphics g, JComponent c)
    {
        super.paint(g, c);

        Rectangle clip = g.getClipBounds();

        Rectangle bounds = table.getBounds();
        // account for the fact that the graphics has already been translated
        // into the table's bounds
        bounds.x = bounds.y = 0;

        //just do not want to copy too much code from BasicTableUI, so comment out following code.
        //code from BasicTableUI comment out begin
//  if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
//                // this check prevents us from painting the entire table
//                // when the clip doesn't intersect our bounds at all
//                !bounds.intersects(clip)) {
//
//            paintDropLines(g);
//      return;
//  }
        //code from BasicTableUI comment out end
        boolean ltr = table.getComponentOrientation().isLeftToRight();

        Point upperLeft = clip.getLocation();
        if(!ltr)
        {
            upperLeft.x++;
        }

        Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
                                     clip.y + clip.height);
        int rMin = table.rowAtPoint(upperLeft);
        int rMax = table.rowAtPoint(lowerRight);
        // This should never happen (as long as our bounds intersect the clip,
        // which is why we bail above if that is the case).
        if(rMin == -1)
        {
            rMin = 0;
        }
        // If the table does not have enough rows to fill the view we'll get -1.
        // (We could also get -1 if our bounds don't intersect the clip,
        // which is why we bail above if that is the case).
        // Replace this with the index of the last row.
        if(rMax == -1)
        {
            rMax = table.getRowCount() - 1;
        }

        int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
        int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
        // This should never happen.
        if(cMin == -1)
        {
            cMin = 0;
        }
        // If the table does not have enough columns to fill the view we'll get -1.
        // Replace this with the index of the last column.
        if(cMax == -1)
        {
            cMax = table.getColumnCount() - 1;
        }
        paintCells(g, rMin, rMax, cMin, cMax);
    }

    private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax)
    {
        JTableHeader header = table.getTableHeader();
        TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();

        TableColumnModel cm = table.getColumnModel();
        int columnMargin = cm.getColumnMargin();

        Rectangle cellRect;
        TableColumn aColumn;
        int columnWidth;
        if(table.getComponentOrientation().isLeftToRight())
        {
            for(int row = rMin; row <= rMax; row++)
            {
                //code from BasicTableUI comment out begin
//                cellRect = table.getCellRect(row, cMin, false);
//                for(int column = cMin; column <= cMax; column++)
//                {
//                    aColumn = cm.getColumn(column);
//                    columnWidth = aColumn.getWidth();
//                    cellRect.width = columnWidth - columnMargin;
//                    if(aColumn != draggedColumn)
//                    {
//                        paintCell(g, cellRect, row, column);
//                    }
//                    cellRect.x += columnWidth;
//                }
                //code from BasicTableUI end
                //code written by sean begin
                cellRect = table.getCellRect(row, cMax, false);
                int maxWidth = 0;
                for(int column = cMax; column >= cMin; column--)
                {
                    aColumn = cm.getColumn(column);
                    columnWidth = aColumn.getWidth();
                    cellRect.width = columnWidth - columnMargin;
                    maxWidth += cellRect.width;
                    if(aColumn != draggedColumn)
                    {
                        paintCell(g, cellRect, row, column, maxWidth);
                    }
                    cellRect.x -= columnWidth;
                    if (table.getValueAt(row, column) != null)
                    {
                        maxWidth = 0;
                    }
                }
                //code written by sean end
            }
        }
        else
        {
            for(int row = rMin; row <= rMax; row++)
            {
                cellRect = table.getCellRect(row, cMin, false);
                aColumn = cm.getColumn(cMin);
                if(aColumn != draggedColumn)
                {
                    columnWidth = aColumn.getWidth();
                    cellRect.width = columnWidth - columnMargin;
                    paintCell(g, cellRect, row, cMin);
                }
                for(int column = cMin + 1; column <= cMax; column++)
                {
                    aColumn = cm.getColumn(column);
                    columnWidth = aColumn.getWidth();
                    cellRect.width = columnWidth - columnMargin;
                    cellRect.x -= columnWidth;
                    if(aColumn != draggedColumn)
                    {
                        paintCell(g, cellRect, row, column);
                    }
                }
            }
        }

        //just do not want to copy too much code from BasicTableUI, so comment out following code.
        //code from BasicTableUI comment out begin
        // Paint the dragged column if we are dragging.
//        if(draggedColumn != null)
//        {
//            paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
//        }
        //code from BasicTableUI comment out end

        // Remove any renderers that may be left in the rendererPane.
        rendererPane.removeAll();
    }

    private void paintCell(Graphics g, Rectangle cellRect, int row, int column)
    {
        paintCell(g, cellRect, row, column, -1);
    }

    private void paintCell(Graphics g, Rectangle cellRect, int row, int column,
                           /** sean's modification begin**/
                           int maxWidth
                           /** sean's modification end**/)
    {
        if(table.isEditing() && table.getEditingRow() == row &&
            table.getEditingColumn() == column)
        {
            Component component = table.getEditorComponent();
            component.setBounds(cellRect);
            component.validate();
        }
        else
        {
            //code from BasicTableUI begin
//            TableCellRenderer renderer = table.getCellRenderer(row, column);
//            Component component = table.prepareRenderer(renderer, row, column);
//            rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
//                                        cellRect.width, cellRect.height, true);
            //code from BasicTableUI end
            //code written by sean begin
            TableCellRenderer renderer = table.getCellRenderer(row, column);
            Component component = table.prepareRenderer(renderer, row, column);
            int width = cellRect.width;
            int height = cellRect.height;
            Dimension preferredSize = component.getPreferredSize();
            if(preferredSize != null && preferredSize.getWidth() != 0 && preferredSize.getHeight() != 0)
            {
                if(maxWidth > 0)
                    width = Math.min(preferredSize.width, maxWidth);
                else
                    width = preferredSize.width;
            }
            rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
                                        width, height, true);
            //code written by sean end
        }
    }

    public static void main(String[] args)
    {

        JFrame frame = new JFrame();
        DefaultTableModel tableModel = new DefaultTableModel(2, 4);
        tableModel.setValueAt("1234567890abcdefg1234567890abcdefg90abcdefg1234567890abcdefg90abcdefg1234567890abcdefg90abcdefg1234567890abcdefg", 0, 0);
//        tableModel.setValueAt("xyz", 0, 1);//try to uncomment to see the difference
        final JTable table = new JTable(tableModel);
        final Font font = new Font("Arial", Font.PLAIN, 12);
        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
        {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                           boolean hasFocus,
                                                           int row, int column)
            {
                Component tableCellRendererComponent =
                    super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if(tableCellRendererComponent instanceof JLabel)
                {
                    JLabel label = (JLabel)tableCellRendererComponent;
                    if(hasFocus && value != null)
                    {
                        FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
                        int width = metrics.stringWidth((String)value) + 20;
                        label.setPreferredSize(new Dimension(width, metrics.getHeight()));
//                        label.setBorder(BorderFactory.createLineBorder(Color.red));
                    }
                    else
                    {
                        label.setPreferredSize(null);
                    }
//                    label.setText("_______________");
                }
                return tableCellRendererComponent;
            }
        });

        table.setUI(new MyBasicTableUI());
        frame.getContentPane().add(table, BorderLayout.CENTER);
        frame.setSize(600, 800);
        frame.setVisible(true);
    }
}

截图如下。仍然需要调整代码,使绘画更好,但无论如何这是实现您想要的正确方法。

在此处输入图像描述

于 2012-03-19T04:56:45.213 回答