背景颜色在JTable中使用JCheckBox闪烁

时间:2016-11-20 15:08:43

标签: 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);

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

注意
使用默认的布尔渲染器来实现这一点仍然有同样的问题,但它不会经常发生

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();
    }
}

1 个答案:

答案 0 :(得分:1)

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

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();
                }
            }
        );
    }
}