Java Swing, Trying to replace boolean check-box in a JTable with an image-icon checkbox

前端 未结 3 1872
忘了有多久
忘了有多久 2021-01-22 08:26

So I have a JTable with check-boxes. I would like to have the check-boxes contain one image when they are \"checked\" and another image when they are \"unchecked\" (i.e., displa

3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-22 09:25

    You'll need to supply you own custom TableCellRenderer that is capable of providing the functionality you want...

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.table.AbstractTableModel;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableModel;
    
    public class TestTableRenderer {
    
        public static void main(String[] args) {
            new TestTableRenderer();
        }
    
        public TestTableRenderer() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                TableModel model = new AbstractTableModel() {
    
                    @Override
                    public int getRowCount() {
                        return 2;
                    }
    
                    @Override
                    public int getColumnCount() {
                        return 1;
                    }
    
                    @Override
                    public Object getValueAt(int rowIndex, int columnIndex) {
                        return rowIndex == 0 ? true : false;
                    }
    
                    @Override
                    public Class getColumnClass(int columnIndex) {
                        return Boolean.class;
                    }
    
                };
                JTable table = new JTable(model);
                table.setDefaultRenderer(Boolean.class, new CustomBooleanCellRenderer());
                setLayout(new BorderLayout());
                add(new JScrollPane(table));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        }
    
        public class CustomBooleanCellRenderer extends JCheckBox implements TableCellRenderer {
    
            private ImageIcon sad;
            private ImageIcon happy;
    
            public CustomBooleanCellRenderer() {
                try {
                    happy = new ImageIcon(ImageIO.read(getClass().getResource("/Happy.png")));
                    sad = new ImageIcon(ImageIO.read(getClass().getResource("/Sad.png")));
                } catch (IOException ex) {
                    Logger.getLogger(TestTableRenderer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
    
            @Override
            public void setSelected(boolean selected) {
                super.setSelected(selected); 
                if (selected) {
                    setIcon(happy);
                } else {
                    setIcon(sad);
                }
            }
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                if (value instanceof Boolean) {
                    boolean selected = (boolean) value;
                    setSelected(selected);
                }
                return this;
            }
        }
    }
    

    Now, you could just as easily use a JLabel or DefaultTableCellRenderer, check the Object value for true/false and set the icon accordingly...but where would the fun be in that ;)

    Updated to include the editor...

    I've rearranged the code slightly to include a cell editor...

    public class CustomCheckBox extends JCheckBox {
    
        private ImageIcon sad;
        private ImageIcon happy;
    
        public CustomCheckBox() {
            try {
                happy = new ImageIcon(ImageIO.read(getClass().getResource("/Happy.png")));
                sad = new ImageIcon(ImageIO.read(getClass().getResource("/Sad.png")));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        @Override
        public void setSelected(boolean selected) {
            super.setSelected(selected);
            if (selected) {
                setIcon(happy);
            } else {
                setIcon(sad);
            }
        }
    
    }
    
    public class CustomBooleanCellRenderer extends CustomCheckBox implements TableCellRenderer {
    
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (value instanceof Boolean) {
                boolean selected = (boolean) value;
                setSelected(selected);
            }
            return this;
        }
    
    }
    
    public class CustomBooleanCellEditor extends AbstractCellEditor implements TableCellEditor {
    
        private CustomCheckBox editor;
    
        public CustomBooleanCellEditor() {
            editor = new CustomCheckBox();
        }
    
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            if (value instanceof Boolean) {
                boolean selected = (boolean) value;
                editor.setSelected(selected);
            }
            return editor;
        }
    
        @Override
        public Object getCellEditorValue() {
            return editor.isSelected();
        }
    
    }
    

    You can apply the in a similar way you did the renderer...

    table.setDefaultEditor(Boolean.class, new CustomBooleanCellEditor());
    

提交回复
热议问题