#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:
Столбец кнопки таблицы показывает мое решение для использования кнопки в качестве средства визуализации / редактора.