Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9165821
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T14:59:47+00:00 2026-06-17T14:59:47+00:00

Following trashgod ‘s excellent example here , I put together a little demo which

  • 0

Following trashgod‘s excellent example here, I put together a little demo which accomplishes a simple task in a probably admittedly convoluted way. The GUI shown below displays a column of icons representing true/false values. If you click an icon, it changes the value to the opposite of whatever it is. Pretty much like a checkbox, but with a different appearance, and more extensible (for example, I could change it in the future to cycle through a dozen symbols rather than just two boolean symbols).

enter image description here

I did it by using a custom editor which is a dummy extension of a JComponent. You never even see this dummy component though, because as soon as it picks up a MousePressed event, it causes the editor to fireEditingStopped(). It works great, except for one weird bug I found. If you click on a symbol to change it, then move your mouse somewhere else on screen and press a keyboard key, it brings up the dummy editor in the last cell clicked (which effectively blanks out the cell), and it stays there until you either move your mouse into the cell or click a different cell.

As a hacky fix to this, I added a line in the renderer which always deselects the entire table after rendering it. This works great, and I have verified that the entire table is indeed deselected. However, despite that, if you press a keyboard key, it still executes the editor for the last edited cell. How can I prevent this behavior? I have other keyboard listeners in my application, and if no cell is selected, I do not think any of their editors should be executed.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.imageio.ImageIO;
import javax.swing.AbstractCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class JTableBooleanIcons {

    private JFrame frame;
    private DefaultTableModel tableModel;
    private JTable table;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    JTableBooleanIcons window = new JTableBooleanIcons();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public JTableBooleanIcons() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        tableModel = new DefaultTableModel(new Object[]{"Words", "Pictures"},0);
        table = new JTable(tableModel);
        table.setRowHeight(40);
        tableModel.addRow(new Object[]{"click icon to change", false});
        tableModel.addRow(new Object[]{"click icon to change", true});
        tableModel.addRow(new Object[]{"click icon to change", false});
        tableModel.addRow(new Object[]{"click icon to change", true});
        tableModel.addRow(new Object[]{"click icon to change", false});
        tableModel.addRow(new Object[]{"click icon to change", true});
        tableModel.addRow(new Object[]{"click icon to change", false});
        tableModel.addRow(new Object[]{"click icon to change", true});

        frame.getContentPane().add(table, BorderLayout.CENTER);

        table.getColumn("Pictures").setCellRenderer(new BooleanIconRenderer());
        table.getColumn("Pictures").setCellEditor(new BooleanIconEditor());

    }

    @SuppressWarnings("serial")
    private class BooleanIconRenderer extends DefaultTableCellRenderer implements TableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                                        boolean hasFocus, int row, int col) {
            String iconFilename = null;
            if ((boolean) value) {
                iconFilename = "yes.png";
                value = true;
            } else {
                iconFilename = "no.png";
                value = false;
            }
            try {
                setIcon(new ImageIcon(ImageIO.read(BooleanIconRenderer.class.getResourceAsStream(iconFilename))));
            } catch (Exception e) {
                System.err.println("Failed to load the icon.");
            }
            if (isSelected) {
                this.setBackground(Color.white);
            } else {
                this.setBackground(Color.white);
            }
            table.getSelectionModel().clearSelection();
            return this;
        }
    }

    @SuppressWarnings("serial")
    private class BooleanIconEditor extends AbstractCellEditor implements TableCellEditor, MouseListener {

        private BooleanComponent boolComp;

        public BooleanIconEditor() {
            boolComp = new BooleanComponent(false);
            boolComp.addMouseListener(this);
        }

        @Override
        public Object getCellEditorValue() {
            return boolComp.getValue();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column) {
            boolComp.setValue(! (boolean) value);
            return boolComp;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            this.fireEditingStopped();
        }

        @Override
        public void mousePressed(MouseEvent e) {
            this.fireEditingStopped();

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            this.fireEditingStopped();
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            this.fireEditingStopped();
        }

        @Override
        public void mouseExited(MouseEvent e) {
            this.fireEditingStopped();
        }

    }

    @SuppressWarnings("serial")
    private class BooleanComponent extends JComponent {
        private boolean value;

        public BooleanComponent(boolean value) {
            this.value = value;
        }

        public boolean getValue() {
            return value;
        }

        public void setValue(boolean value) {
            this.value = value;
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T14:59:49+00:00Added an answer on June 17, 2026 at 2:59 pm

    The reason for your problem is that you are actually not rendering anything within the editor. You’re relying on the fact that the user is only ever going to “click” the cell to change it’s value. I’d consider this a little short-sighted, but, it’s you program.

    To fix it immediately, simply add…

    @Override
    public boolean isCellEditable(EventObject e) {
        return (e instanceof MouseEvent);
    }
    

    To you BooleanIconEditor.

    On a side note.

    In you cell renderer, you shouldn’t be loading images. These should have been pre-cached as part of the constructor or even better, as static field variables. You may be doing this, but just in case.

    Updated

    While I’m on the subject. You should avoid changing the state of the table from within the renderer. This is really unsafe and could end you up in an infinite loop of hell as the table tries to re-render the changes you’ve made, again and again…

    If you really want to hide the selection (I’m not sure why you would), you could either set the table’s selection to match the tables background color OR make it a transparent color. Don’t forget to change the selection foreground as well 😉

    Update #2

    Example with keyboard support 😉 – couldn’t resist…

    public class JTableBooleanIcons {
    
        private JFrame frame;
        private DefaultTableModel tableModel;
        private JTable table;
        private ImageIcon yesIcon;
        private ImageIcon noIcon;
    
        /**
         * Launch the application.
         */
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        JTableBooleanIcons window = new JTableBooleanIcons();
                        window.frame.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * Create the application.
         */
        public JTableBooleanIcons() {
            try {
                yesIcon = (new ImageIcon(ImageIO.read(BooleanIconRenderer.class.getResourceAsStream("/yes.png"))));
                noIcon = (new ImageIcon(ImageIO.read(BooleanIconRenderer.class.getResourceAsStream("/no.png"))));
            } catch (Exception e) {
                e.printStackTrace();
            }
            initialize();
        }
    
        /**
         * Initialize the contents of the frame.
         */
        private void initialize() {
            frame = new JFrame();
            frame.setBounds(100, 100, 450, 400);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            tableModel = new DefaultTableModel(new Object[]{"Words", "Pictures"}, 0);
            table = new JTable(tableModel);
            table.setRowHeight(40);
            tableModel.addRow(new Object[]{"click icon to change", false});
            tableModel.addRow(new Object[]{"click icon to change", true});
            tableModel.addRow(new Object[]{"click icon to change", false});
            tableModel.addRow(new Object[]{"click icon to change", true});
            tableModel.addRow(new Object[]{"click icon to change", false});
            tableModel.addRow(new Object[]{"click icon to change", true});
            tableModel.addRow(new Object[]{"click icon to change", false});
            tableModel.addRow(new Object[]{"click icon to change", true});
    
            frame.getContentPane().add(table, BorderLayout.CENTER);
    
            table.getColumn("Pictures").setCellRenderer(new BooleanIconRenderer());
            table.getColumn("Pictures").setCellEditor(new BooleanIconEditor());
    
        }
    
        @SuppressWarnings("serial")
        private class BooleanIconRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
    
            public BooleanIconRenderer() {
            }
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int col) {
                super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, col);
                if ((boolean) value) {
                    setIcon(yesIcon);
                } else {
                    setIcon(noIcon);
                }
                return this;
            }
        }
    
        @SuppressWarnings("serial")
        private class BooleanIconEditor extends AbstractCellEditor implements TableCellEditor, MouseListener {
    
            private BooleanComponent boolComp;
            private boolean isMouseEvent;
    
            public BooleanIconEditor() {
                boolComp = new BooleanComponent(false);
                boolComp.addMouseListener(this);
                InputMap im = boolComp.getInputMap(JComponent.WHEN_FOCUSED);
                ActionMap am = boolComp.getActionMap();
    
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "click");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "click");
    
                am.put("click", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("Clicked");
                        boolComp.setValue(!boolComp.getValue());
                    }
                });
    
            }
    
            @Override
            public boolean isCellEditable(EventObject e) {
                isMouseEvent = e instanceof MouseEvent;
                return true; //(e instanceof MouseEvent);
            }
    
            @Override
            public Object getCellEditorValue() {
                return boolComp.getValue();
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table,
                    Object value, boolean isSelected, int row, int column) {
                boolean state = (boolean) value;
                if (isMouseEvent) {
                    state = !state;
                }
                boolComp.setValue(state);
                boolComp.setOpaque(isSelected);
                boolComp.setBackground(table.getSelectionBackground());
                return boolComp;
            }
    
            @Override
            public void mouseClicked(MouseEvent e) {
                this.fireEditingStopped();
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                this.fireEditingStopped();
    
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                this.fireEditingStopped();
            }
    
            @Override
            public void mouseEntered(MouseEvent e) {
                this.fireEditingStopped();
            }
    
            @Override
            public void mouseExited(MouseEvent e) {
                this.fireEditingStopped();
            }
        }
    
        @SuppressWarnings("serial")
        private class BooleanComponent extends JLabel {
    
            private boolean value;
    
            public BooleanComponent(boolean value) {
                this.value = value;
            }
    
            public boolean getValue() {
                return value;
            }
    
            public void setValue(boolean value) {
                this.value = value;
                if (value) {
                    setIcon(yesIcon);
                } else{
                    setIcon(noIcon);
                }
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Following are the simple statements in the irb shell. What does nil in the
Following is the Play 2 app, https://github.com/playframework/Play20/tree/master/samples/java/forms Which portrays Dynamic form binding where form
Following on from my previous question: Simple inner join in linq How would I
Following code is an example of text placed into a textarea from a database.
Following the instruction found here: Insert a datasheet into a form I get an
Following those conversations: Can I vectorize a calculation which depends on previous elements sapply?
Following is my sql query in which i am trying to get the names
Following is my sql query which worked fine when i ran it from phpmyadmin
Following is my query in which I am trying to insert those records whose
Following the instructions here , but i get the error unable to autowire WebApplicationContext.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.