Wcześniej wybrany edytor wyzwalaczy komórki JTable w naciśnięciu klawisza, nawet jeśli został wyraźnie odznaczony

Następującytrashgodto doskonały przykładtutaj, Stworzyłem małe demo, które realizuje proste zadanie w prawdopodobnie pewnie zawiły sposób. GUI pokazane poniżej wyświetla kolumnę ikon reprezentujących wartości true / false. Jeśli klikniesz ikonę, zmieni ona wartość na przeciwną. Prawie jak pole wyboru, ale o innym wyglądzie i bardziej rozszerzalnym (na przykład, mógłbym to zmienić w przyszłości, aby przechodzić przez kilkanaście symboli zamiast tylko dwóch symboli boolowskich).

Zrobiłem to, używając niestandardowego edytora, który jest fałszywym rozszerzeniem komponentu JC. Jednak nawet nie widzisz tego fałszywego komponentu, ponieważ jak tylko wybierzeMousePressed zdarzenie powoduje, że edytorfireEditingStopped(). Działa świetnie, z wyjątkiem jednego dziwnego błędu, który znalazłem. Jeśli klikniesz symbol, aby go zmienić, a następnie przesuń mysz w inne miejsce na ekranie i naciśnij klawisz klawiatury, spowoduje to wyświetlenie fikcyjnego edytora w ostatniej klikniętej komórce (co skutecznie usunie komórkę) i pozostanie tam, aż przenieś mysz do komórki lub kliknij inną komórkę.

Jako hacky naprawić to, dodałem wiersz w rendererze, który zawsze odznacza całą tabelę po jej renderowaniu. To działa świetnie i sprawdziłem, że cała tabela jest rzeczywiście odznaczona. Jednak mimo to, jeśli naciśniesz klawisz klawiatury, tonadal wykonuje edytor ostatniej edytowanej komórki. Jak mogę zapobiec temu zachowaniu? W mojej aplikacji mam innych słuchaczy klawiatury, a jeśli nie wybrano żadnej komórki, nie sądzę, aby którykolwiek z ich edytorów był wykonywany.

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

questionAnswers(2)

yourAnswerToTheQuestion