2

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., display images instead of a checked or unchecked box). Is there a way to do this? I've tried fooling with the TableCellRenderer that returns a JLabel with an ImageIcon but it was not really very effective.

More specifically, when the box is checked or unchecked the right images are there, but when the user is changing the check-box state (while the mouse is down) the original checked/unchecked images appear

This is the TableCellRenderer I tried (I have also tried it with JPanels but this was ineffective as well

public class CrassusEventTableCellEyeRenderer extends JCheckBox implements TableCellRenderer {

    static Icon greyEye;
    static Icon blackEye;

    {//STATIC CODE BLOCK
        try {
            greyEye = new ImageIcon(ImageIO.read(new File("icons/shittyTest.png")));

            blackEye = new ImageIcon(ImageIO.read(new File("icons/blackEye.png")));
        } catch (IOException e) {
            greyEye = null;
            blackEye = null;
        }
    }

    public CrassusEventTableCellEyeRenderer(){
        super();
        this.addItemListener(new IsCheckedItemListener());
        setIcon(greyEye);
    }

//commented out code that I have tried in place of the IsCheckedItemListener
    /*
    @Override
    public void setSelected(boolean sel){
        super.isSelected();
        if(sel)
            setIcon(blackEye);
        else
            setIcon(greyEye);
    }
    */

    public class IsCheckedItemListener implements ItemListener{

        @Override
        public void itemStateChanged(ItemEvent e) {
            if(isSelected())
                setIcon(blackEye);
            else
                setIcon(greyEye);
        }

    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        System.out.println("value: "+value+", row: "+row+", column: "+column);
        if(value instanceof Boolean){
            setSelected(((Boolean) value).booleanValue());
        }
        return this;
    }

}
  • *"I've tried.."* For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Apr 12 '13 at 05:13
  • `one image when they are "checked" and another image when they are "unchecked"` What is it that you do after achieving this? Is it just for fun or you are trying to achieve something? B'coz by looking at the image the end user will not be able to recognize what it meant. – Amarnath Apr 12 '13 at 07:56
  • @Che there is not enough room in our interface for a description by the check-boxes; I will also try and get a description next to the cursor on mouse-over. Think the "eye" and "lock" in the photo-shop layer interface – the_underscore_key Apr 12 '13 at 18:03

3 Answers3

2

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());
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    I tried this, it worked as well as what I had before, but has the same problem. When the mouse is down on the check-box, the original checked/unchecked box image appears, although it works fine after the box is selected. I apologize for not stating my problem clearly the first time; I have edited the question – the_underscore_key Apr 13 '13 at 18:40
  • There is a much easier and working approach w/o extending the Renderer/Editor. You simply make use of the JCheckBox's methods setIcon() and setSelectedIcon() - and there you are. See here: [Trying to Replace Boolean CheckBox renderer/editor in JTable](https://stackoverflow.com/a/56877885/7249306) – Denis Abakumov Oct 23 '21 at 16:59
  • @DenisAbakumov Depends on what you're trying to do - your example sets it for a single column, mine, sets for all `Boolean` types – MadProgrammer Oct 23 '21 at 21:38
1

You would have to use the

isSelected

Method to see if the box is checked or not and by that you can use a if statement and if it is checked you use

checkBox.setIcon(myIcon);

Note that u can also u an ItemListener for the task of knowing if the box is selected or not.

Question answeared using following resources: http://www.roseindia.net/java/example/java/swing/CustomizedCheckBox.shtml

How to check that a JCheckBox is checked?

Community
  • 1
  • 1
User
  • 1,458
  • 3
  • 16
  • 40
  • 1
    I tried this, it worked as well as what I had before, but has the same problem. When the mouse is down on the check-box, the original checked/unchecked box image appears, although it works fine after the box is selected. I apologize for not stating my problem clearly the first time; I have edited the question. **also**, be aware that this is in a TableCellRenderer, not just a JCheckBox on its own. It is possible that that is the source of the issue, I am not sure – the_underscore_key Apr 13 '13 at 18:42
0

Assuming that you have just a normal JTable you may set appropriate icons in renderer and editor:

public void setIcons(Jtable table, int column, Icon icon, Icon selectedIcon) {
    JCheckBox cellRenderer = (JCheckBox) table.getCellRenderer(0, column);
    cellRenderer.setSelectedIcon(selectedIcon);
    cellRenderer.setIcon(icon);

    DefaultCellEditor cellEditor = (DefaultCellEditor) table.getCellEditor(0, column);
    JCheckBox editorComponent = (JCheckBox) cellEditor.getComponent();
    editorComponent.setSelectedIcon(selectedIcon);
    editorComponent.setIcon(icon);
}
andronix
  • 124
  • 9