【问题标题】:JTable change cell background at mouse click - after release change background back?JTable 在鼠标单击时更改单元格背景 - 发布后更改背景?
【发布时间】:2011-11-07 21:25:13
【问题描述】:

我的问题是,如何解决以下问题:

如果我单击 JTable 中的单元格,我想更改其背景。如果我松开鼠标按钮,我希望背景变回正常颜色。

这可能吗?

你好

【问题讨论】:

    标签: java swing jtable


    【解决方案1】:

    为了在视觉领域做这件事,你需要

    • 一个 MouseListener,它在按下时在单元格坐标中设置一些状态,并在释放时重置该状态
    • PropertyChangeListener 侦听在更改时重绘单元格的状态
    • 自定义渲染器,为标记的单元格设置自定义背景

    监听器的一些代码

        MouseListener l = new MouseAdapter() {
    
            /** 
             * @inherited <p>
             */
            @Override
            public void mousePressed(MouseEvent e) {
                JTable table = (JTable) e.getComponent();
                int col = table.columnAtPoint(e.getPoint());
                int row = table.rowAtPoint(e.getPoint());
                if (col < 0 || row < 0) {
                    table.putClientProperty("pressedCell", null);
                } else {
                    table.putClientProperty("pressedCell", new Point(col, row));
                }
            }
    
            /** 
             * @inherited <p>
             */
            @Override
            public void mouseReleased(MouseEvent e) {
                ((JTable) e.getComponent()).putClientProperty("pressedCell", null);
            }
    
        };
        table.addMouseListener(l);
        PropertyChangeListener property = new PropertyChangeListener() {
    
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                JTable table = (JTable) evt.getSource();
                Point cell = evt.getNewValue() != null ? 
                        (Point) evt.getNewValue() : (Point) evt.getOldValue();
                if (cell != null) table.repaint(table.getCellRect(cell.y, cell.x, false));        
            }
    
        };
        table.addPropertyChangeListener("pressedCell", property);
    

    在 SwingX 中突出显示单元格(无法抗拒:-)

        HighlightPredicate predicate = new HighlightPredicate() {
    
            @Override
            public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
                Point p = (Point) adapter.getComponent().getClientProperty("pressedCell");
                return p != null && p.x == adapter.column && p.y == adapter.row;
    
            }
        };
        table.addHighlighter(new ColorHighlighter(predicate, Color.YELLOW, null, Color.YELLOW, null));
    

    对于核心 Swing,实现自定义 TableCellRenderer 或子类化 JTable 并重写 prepareRenderer 以根据单元格标志设置背景颜色,如 Rob 的 Table Row Rendering 中所述

    【讨论】:

    • 为什么在 JTable 上添加另一个监听器(而且非常重)和 MouseListener 会使事情变得复杂,它每秒生成超过 1.000 个事件,1)并不是那么适得其反,那么可能是渲染器会更轻量级的监听器,2) 同意是否存在不可压缩的 HightLighter,然后有另一个监听器可能不会生成预期的事件..
    • +1 :你是对的。这是用户正在寻找的。也很有趣,我之前从未听说过 ColorHighlighter
    • @Overbose 这是一个 SwingX 荧光笔 :-)
    • (该死,我以为我在一小时前已经发送了这条评论,有时这个系统让我感到害怕......“等待 15 秒等待下一条评论”)@mKorbel 因为看似简单的解决方案(就像你和建议过量)不满足要求,因此根本不是解决方案:-)
    • @kleopatra 1) systems freaks me - FW 问题 2) 你能具体一点吗,因为在这里实现,在那里实现,没有明确的 --> :-),3) 真正唯一的方法是实现鼠标适配器和指针
    【解决方案2】:

    在您的渲染器中,您必须覆盖 hasFocus

    例如

    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.table.*;
    
    public class TableRenderer extends JFrame {
    
        private static final long serialVersionUID = 1L;
        private JTable table;
        private String[] columnNames = {"Date", "String", "Centered", "Integer", "Boolean"};
        private Object[][] data = {
            {new Date(), "A", "A", new Integer(1), true},
            {new Date(), "B", "B", new Integer(2), false},
            {new Date(), "C", "C", new Integer(10), null},
            {new Date(), "D", "D", new Integer(4), false}
        };
    
        public TableRenderer() {
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            table = new JTable(model) {
    
                private static final long serialVersionUID = 1L;
                //  Returning the Class of each column will allow different
                //  renderers to be used based on Class
    
                @Override
                public Class getColumnClass(int column) {
                    return getValueAt(0, column).getClass();
                }
            };
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane scrollPane = new JScrollPane(table);
            getContentPane().add(scrollPane);
    
            //  Override default renderer on a specific Class
            TableCellRenderer colorRenderer = new ColorRenderer();
            table.setDefaultRenderer(String.class, colorRenderer);
    
            //  Override default renderer for a specific column
            DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
            centerRenderer.setHorizontalAlignment(JLabel.CENTER);
            table.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    TableRenderer frame = new TableRenderer();
                    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        /*
         **  Color the focused cell
         */
        private class ColorRenderer extends DefaultTableCellRenderer {
    
            private static final long serialVersionUID = 1L;
    
            @Override
            public Component getTableCellRendererComponent(
                    JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (hasFocus) {
                    setBackground(Color.cyan);
                } else if (isSelected) {
                    setBackground(table.getSelectionBackground());
                } else {
                    setBackground(table.getBackground());
                }
                return this;
            }
        }
    }
    

    【讨论】:

    • 如果我使用 defaultcellrenderer,你有一个小例子吗?
    • +1:另一种方式,而不是 ListSelectionModel。我不知道这是否是最好的解决方案。
    • @0verbose hmmm 只是我确定这是一条捷径,+1,但是您的历史中的另一个问题是,是否有一些关于您在 JTable 中不可排序的行的消息,您有任何进展吗有了那个???,对于您在此处发布的提示,需要实现这个tips4java.wordpress.com/2008/10/20/table-select-all-editor
    • @mKorbel:我用一种变通方法解决了,但我不记得如何了 :) 。我正在查看正确的代码,但我找不到它。
    • 感谢您的代码,但这并不是我想要的。也许我的解释不够清楚。我需要的是一些像“按钮”行为的想法。如果我单击单元格并按住鼠标按钮,例如颜色应该变为青色,但如果我释放按钮,它的外壳会变回。问候好吧
    【解决方案3】:

    是的,这是可能的。 使用自定义 ListSelectionModel 并将您的 JTable 设置为使用它:setSelectionModel()

    这是example

    【讨论】:

    • @0verbose 确保周一情况更糟 :-)
    猜你喜欢
    • 2011-09-23
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2016-04-27
    相关资源
    最近更新 更多