actionPerformed на JButton как неверно вызываемый TableCellEditor при наведении курсора мыши

#java #swing #jbutton #actionlistener #tablecelleditor

#java #swing #jbutton #actionlistener #tablecelleditor

Вопрос:

Я пытаюсь использовать JButton as TableCellRenderer и TableCellEditor для моего JTable . В моем тестовом сценарии у меня есть 5 строк, каждая из которых показывает JButton средство визуализации и редактор (разные экземпляры кнопок для редактора и средства визуализации). Когда я нажимаю на одну кнопку в первый раз actionPerformed , вызывается кнопка редактора, когда я ОТПУСКАЮ кнопку мыши. Когда я нажимаю на другую кнопку в другой строке, actionPerformed событие -Событие кнопки редактора уже вызывается, когда я нажимаю кнопку мыши вниз ( MOUSE_PRESSED ). Такое поведение кажется неправильным. Обычно actionPerformed событие -event вызывается при отпускании кнопки мыши, а не при ее нажатии. При последующем нажатии другой кнопки в другой строке actionPerformed снова вызывается правильно при отпускании кнопки мыши, при следующем нажатии кнопки в другой строке actionPerformed снова (неправильно) вызывается MOUSE_DOWN и так далее.

При перемещении фокуса из таблицы и последующем нажатии на кнопку, actionPerformed вызывается правильно при отпускании кнопки мыши. Также, когда редактор строк таблицы в строке, в которой находится кнопка, на которую нужно нажать, сначала фокусируется (активируется), а затем нажимается кнопка, поведение также является правильным. Тогда единственная ситуация, когда это не работает, — это когда активен редактор ячеек таблицы, а затем нажата кнопка в другой строке таблицы.

Сравнивая трассировки стека при actionPerformed вызове в обоих случаях, я обнаружил, что в неправильном случае DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEvent BasicButtonListener.focusLost(FocusEvent) вызываются и, которые оба выглядят подозрительно для меня.

Вот небольшой демонстрационный код для моей проблемы:

 import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class TableButtonTest extends JFrame
{

    private JTable  table;

    public TableButtonTest()
    {
        super("TableButtonTest");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel contentPane = new JPanel(new GridLayout(1, 0));
        contentPane.setOpaque(true);
        setContentPane(contentPane);

        table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        add(table);

        setPreferredSize(new Dimension(600, 200));

        TableCellRenderer defaultBtnRenderer = new TableCellRenderer()
        {
            private JButton btn = new JButton("aa");

            public Component getTableCellRendererComponent(JTable _table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column)
            {
                return btn;
            }
        };

        table.getColumnModel().getColumn(0).setCellRenderer(defaultBtnRenderer);
        table.getColumnModel().getColumn(0).setCellEditor(new ButtonEditor());

        pack();
        setVisible(true);

    }

    public class ButtonEditor extends AbstractCellEditor implements TableCellEditor
    {
        private JButton btn = new JButton("bb");
        {
            btn.addActionListener(new ActionListener()
            {

                public void actionPerformed(ActionEvent e)
                {
                    System.out.println("BUTTON EVENT");
                }
            });
        }

        public Component getTableCellEditorComponent(JTable _table, Object value, boolean isSelected,
            int row, int column)
        {
            return btn;
        }

        public Object getCellEditorValue()
        {
            return null;
        }
    }

    class MyTableModel extends AbstractTableModel
    {
        public int getColumnCount()
        {
            return 1;
        }

        public int getRowCount()
        {
            return 5;
        }

        public Object getValueAt(int row, int col)
        {
            return null;
        }

        @Override
        public boolean isCellEditable(int row, int col)
        {
            return true;
        }
    }

    public static void main(String[] args)
    {
        new TableButtonTest();
    }
}
  

Когда вы запускаете программу и нажимаете любую из кнопок «aa», она превращается в «bb» (что указывает на то, что вместо средства визуализации отображается редактор), а когда вы отпускаете кнопку мыши, «СОБЫТИЕ КНОПКИ» выводится на стандартный вывод. Если вы нажмете на другую кнопку в другой строке, она также превратится в «bb», но «СОБЫТИЕ КНОПКИ» уже напечатано в стандартный вывод до того, как вы отпустите кнопку мыши. А также прямоугольник фокуса вокруг текста кнопки не отображается.

Я протестировал это поведение с Java 1.6.0_26 и 1.6.0_27. Когда я использовал 1.5.0_17, событие ухудшилось: при нажатии на вторую кнопку НЕ было вызвано НИКАКОГО actionPerformed, отображалась только кнопка «bb». Затем третий щелчок снова сработал правильно, четвертый — нет и так далее. Таким образом, разница с Java 1.6 заключается в том, что в 1.6 при втором (и четвертом, …) щелчке actionPerformed вызывается при отпускании кнопки мыши, в 1.5 не вызывается вообще.

Но меня не волнует 1.5, я просто хочу, чтобы он работал с 1.6.

Что я могу сделать, чтобы это сработало?

Спасибо.

Комментарии:

1. Из того, что я понимаю, существует простая реализация ActionListeners и более универсальная для системы реализация MouseListeners . Это может объяснить различия между поколениями API… Однако это не из источника, поэтому я оставляю это в качестве комментария. — Кроме того, вы можете просто использовать MouseListeners вместо ActionListeners? Я знаю, что обычно не одобряется использование низкоуровневых прослушивателей, но это может быть поводом для этого.

Ответ №1:

Столбец кнопки таблицы показывает мое решение для использования кнопки в качестве средства визуализации / редактора.