java - JTable中使用JCheckBox背景颜色闪烁

标签 java swing jtable

在我的 JTable 上,我使用 prepareRenderer 函数设置行的背景颜色。我还删除了焦点边框,并在稍后的代码中禁用了行选择。

JTable table = new JTable() {
    private static final long serialVersionUID = -2965586838134675413L;
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        c.setBackground(row % 2 == 1 ? Color.WHITE : new Color(255, 245, 248));
        ((JComponent) c).setBorder(null);
        return c;
    }
};

DefaultTableModel tableModel = new DefaultTableModel(sampleData, headers) {
    private static final long serialVersionUID = 9186050244728809804L;

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch(columnIndex) {
            case 0:
                return Boolean.class;
            default:
                return String.class;
        }
    }


    @Override
    public boolean isCellEditable(int row, int column) {
        switch(column) {
            case 0:
                return true;
            default:
                return false;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void setValueAt(Object aValue, int row, int column) {
        if (aValue instanceof Boolean && column == 0) {
            //System.out.println(aValue);
            Vector<Boolean> rowData = (Vector<Boolean>) getDataVector().get(row);
            rowData.set(0, (boolean) aValue);
            fireTableCellUpdated(row, column);
        }
    }
};

table.setModel(tableModel);
table.setRowSelectionAllowed(false);

问题是当我点击JCheckBoxes时,背景颜色切换为白色,同时按下鼠标按钮。有没有办法在单击 JCheckBox 时保持颜色不发生变化?

注意
使用默认的 boolean 渲染器来实现这一点仍然存在相同的问题,但它不会经常发生

private class BooleanRenderer extends JCheckBox implements TableCellRenderer
{
    private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);

    public BooleanRenderer() {
        super();
        setHorizontalAlignment(JLabel.CENTER);
        setBorderPainted(true);
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            super.setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
        }
        setSelected((value != null && ((Boolean)value).booleanValue()));
        setBorder(noFocusBorder);

        return this;
    }
}

table.setDefaultRenderer(Boolean.class, new BooleanRenderer())

注释 2
我还尝试将 MouseListener 添加到 JCheckBox 但这不起作用,因为鼠标监听器似乎没有附加到 JCheckBox

JTable fileList = new JTable() {
    private static final long serialVersionUID = -2965586838134675413L;
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        c.setBackground(row % 2 == 1 ? Color.WHITE : new Color(255, 245, 248));
        ((JComponent) c).setBorder(null);

        if(c instanceof JCheckBox) {
            c.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    setBackground(row % 2 == 1 ? Color.WHITE : new Color(255, 245, 248));
                }

                public void mousePressed(MouseEvent e) {
                    setBackground(row % 2 == 1 ? Color.WHITE : new Color(255, 245, 248));
                }

                public void mouseReleased(MouseEvent e) {
                    setBackground(row % 2 == 1 ? Color.WHITE : new Color(255, 245, 248));
                }
            });
        }
        return c;
    }
};

使用第一个代码示例编辑 SSSCE

import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class JTableTest extends JFrame {
    private JTableTest()  {
        super("Button Layout");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        pack();
        setVisible(true);
    }

    JPanel panel = new JPanel(new GridLayout(1, 1));
    JScrollPane scroll = new JScrollPane();

    private void createPanel() {
        Object[] headers = {"Select", "Title", "Artist", "Length"};
        Object[][] sampleData = {{true, "Bat Outta Hell", "Meat Loaf", "673"},
                {false, "Spanish Train", "Chris De Burgh", "358"}};
        JTable table = new JTable() {
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                c.setBackground(row % 2 == 1 ? Color.WHITE : Color.RED);
                ((JComponent) c).setBorder(null); //Left in so it is easier to see problem
                return c;
            }
        };

        DefaultTableModel tableModel = new DefaultTableModel(sampleData, headers) {
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                switch(columnIndex) {
                    case 0:
                        return Boolean.class;
                    default:
                        return String.class;
                }
            }
        };

        table.setModel(tableModel);
        table.setRowSelectionAllowed(false); //Left in so it is easier to see problem

        scroll.getViewport().add(table);
        panel.add(scroll);
        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        new JTableTest();
    }
}

最佳答案

您的 JTable 实例中缺少 prepareEditor 覆盖,我在您的示例中添加了一个。当您单击该复选框时,显示的是编辑器组件而不是渲染器组件。您还需要准备该组件以获得您想要的颜色。

import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

@SuppressWarnings("serial")
public class JTableTest extends JFrame {
    private JTableTest()  {
        super("Button Layout");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        pack();
        setVisible(true);
    }

    JPanel panel = new JPanel(new GridLayout(1, 1));
    JScrollPane scroll = new JScrollPane();

    private void createPanel() {
        Object[] headers = {"Select", "Title", "Artist", "Length"};
        Object[][] sampleData = {{true, "Bat Outta Hell", "Meat Loaf", "673"},
                {false, "Spanish Train", "Chris De Burgh", "358"}};
        JTable table = new JTable() {
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                c.setBackground(row % 2 == 1 ? Color.WHITE : Color.RED);
                ((JComponent) c).setBorder(null); //Left in so it is easier to see problem
                return c;
            }

            @Override
            public Component prepareEditor(TableCellEditor editor, int row, int column) {
                Component c = super.prepareEditor(editor, row, column);
                c.setBackground(row % 2 == 1 ? Color.WHITE : Color.RED);
                ((JComponent) c).setBorder(null); //Left in so it is easier to see problem
                return c;
            }
        };

        DefaultTableModel tableModel = new DefaultTableModel(sampleData, headers) {
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                switch(columnIndex) {
                    case 0:
                        return Boolean.class;
                    default:
                        return String.class;
                }
            }
        };

        table.setModel(tableModel);
        table.setRowSelectionAllowed(false); //Left in so it is easier to see problem

        scroll.getViewport().add(table);
        panel.add(scroll);
        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater (
            new Runnable() {
                @Override
                public void run() {
                    new JTableTest();
                }
            }
        );
    }
}

关于java - JTable中使用JCheckBox背景颜色闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40705616/

相关文章:

java - 获取线程的返回值

java - For 循环显示前一个值和下一个值

java - 如何过滤 JTable 中的行?

java - 如何使用 trie 设计字典应用程序?

java - 使用 LinkedBlockingQueue 并刷新到 mysql

java - 为什么需要为 Java Swing 应用程序设置布局管理器?

java - DefaultTableModel getValueAt 方法生成看似随机的结果

java - JTable 和线程

java - 在 JTextPane 中逐行读取文本

java - java 布局的问题