4

列中的小部件JTable应该与普通小部件无法区分,对吧?似乎存在行为差异,以Swing 文档为例,并将鼠标移到Vegetarian列中的复选框上......他们根本没有反应。我知道这些只是小部件代理,所以必须手动完成突出显示,那么我将如何解决这个问题?我尝试widget.requestFocusInWindow();mouseMoved()代理小部件事件处理程序但没有成功。还有其他解决方法吗?

4

3 回答 3

6

您可以创建自己的应用翻转效果的单元格渲染器。然后,添加一个鼠标侦听器来跟踪鼠标移动并重新绘制相关单元格。您需要将效果应用到光标下的当前单元格并清除上一个单元格。

下面是一个简短的示例,它在复选框渲染器上演示了这种方法。该示例扩展了 default BooleanRenderer。唯一的变化是getModel().setRollover(...)getTableCellRendererComponent().

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class TableRolloverDemo {
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("TableRolloverDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JTable table = new JTable();

        final DefaultTableModel model = new DefaultTableModel(new Object[][] {
                { false }, { false }, { true }, { true } },
                new Object[] { "Column" }) {
            public Class<?> getColumnClass(int columnIndex) {
                return Boolean.class;
            }
        };

        RolloverMouseAdapter rolloverAdapter = new RolloverMouseAdapter(table);
        RolloverBooleanRenderer renderer = new RolloverBooleanRenderer(rolloverAdapter);

        table.addMouseListener(rolloverAdapter);
        table.addMouseMotionListener(rolloverAdapter);

        table.setDefaultRenderer(Boolean.class, renderer);
        table.setModel(model);

        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class RolloverMouseAdapter extends MouseAdapter {
        private int row = -1;
        private int column = -1;
        private JTable table;

        public RolloverMouseAdapter(JTable table) {
            this.table = table;
        }

        public boolean isRolloverCell(int row, int column) {
            return this.row == row && this.column == column;
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            int lastRow = row;
            int lastColumn = column;

            row = table.rowAtPoint(e.getPoint());
            column = table.columnAtPoint(e.getPoint());

            if (row == lastRow && column == lastColumn)
                return;

            if (row >= 0 && column >= 0) {
                table.repaint(table.getCellRect(row, column, false));
            }
            if (lastRow >= 0 && lastColumn >= 0) {
                table.repaint(table.getCellRect(lastRow, lastColumn, false));
            }
        }

        @Override
        public void mouseExited(MouseEvent e) {
            if (row >= 0 && column >= 0) {
                table.repaint(table.getCellRect(row, column, false));
            }
            row = column = -1;
        }

    }

    static class RolloverBooleanRenderer extends JCheckBox implements
            TableCellRenderer, UIResource {
        private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
        private RolloverMouseAdapter adapter;

        public RolloverBooleanRenderer(RolloverMouseAdapter adapter) {
            super();
            this.adapter = adapter;
            setHorizontalAlignment(JLabel.CENTER);
            setBorderPainted(true);
        }

        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {

            getModel().setRollover(adapter.isRolloverCell(row, column));

            if (isSelected) {
                setForeground(table.getSelectionForeground());
                super.setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(table.getBackground());
            }
            setSelected((value != null && ((Boolean) value).booleanValue()));

            if (hasFocus) {
                setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
            } else {
                setBorder(noFocusBorder);
            }

            return this;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
于 2012-11-09T05:50:56.620 回答
3

它是翻转(或缺少翻转)使表格中的小部件看起来死了。如果JPanel是真正的小部件容器,为什么JTableJTree不是?

两者都JTable使用JTree享元模式进行渲染。默认渲染器和编辑器没有内在的鼠标悬停行为。正如@Max所示,您必须自己提供所需的行为。

于 2012-11-09T18:46:54.880 回答
0

Jtable 不会将真实组件放入单元格中。他们只使用组件的绘制方法来呈现单元格内容。

于 2012-11-09T14:38:29.517 回答