英文:
JTable: send key event to all selected components to check all selected checkboxes
问题
我有一个带有复选框的JTable
(因为getColumnClass
是Boolean
)。用户选择了多行,并点击空格键
,但只有lead selection
的复选框会收到KeyEvent
并变为选中状态。
如何检查所有选中的复选框?
这看起来是一个非常简单的任务,但我找不到“官方”的方法来做到这一点,我也不想使用hack。
我可以在我的表格中重写processKeyEvent
,并在模型中物理地设置所有值为true
,但这看起来不太好。
英文:
I have JTable
with checkboxes (because getColumnClass
is Boolean
).
User selects several rows, and clicks space
but only "lead selection" checkbox gets KeyEvent
and becomes checked.
How can I check all selected checkboxes?
It looks like a very simple task, but I can't find "official" way to do that, and I do not want to use hacks.
I can override processKeyEvent
in my table and physically set true
to all values in model, but it doesn't look good.
答案1
得分: 2
我遵循了@camickr和@Jean Willian S. J的建议,并进行了以下操作:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
public class TableTest {
private static final int CHECKBOX_COL = 0;
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
var frame = new JFrame("TableTest");
Object[][] data = {new Object[]{true, "Foo"}, new Object[]{false, "Buz"}};
MyModel dm = new MyModel(data, new Object[]{"Enabled", "Name"});
var table = new JTable(dm);
var invertSelected = "InvertSelected";
table.getInputMap().remove(KeyStroke.getKeyStroke("SPACE"));
table.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), invertSelected);
table.getActionMap().put(invertSelected, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
TableModel model = table.getModel();
for (int selectedRow : table.getSelectedRows()) {
var row = table.convertRowIndexToModel(selectedRow);
var value = !(Boolean) model.getValueAt(row, CHECKBOX_COL);
model.setValueAt(value, row, CHECKBOX_COL);
}
}
});
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
frame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
});
}
private static class MyModel extends DefaultTableModel {
public MyModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
@Override
public boolean isCellEditable(int row, int column) {
return column == CHECKBOX_COL;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return (columnIndex == CHECKBOX_COL ? Boolean.class : String.class);
}
}
}
现在它可以正常工作。谢谢大家。
英文:
I followed @camickr and @Jean Willian S. J 's suggestion, and did:
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
public class TableTest {
private static final int CHECKBOX_COL = 0;
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
var frame = new JFrame("TableTest");
Object[][] data = {new Object[]{true, "Foo"}, new Object[]{false, "Buz"}};
MyModel dm = new MyModel(data, new Object[]{"Enabled", "Name"});
var table = new JTable(dm);
var invertSelected = "InvertSelected";
table.getInputMap().remove(KeyStroke.getKeyStroke("SPACE"));
table.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), invertSelected);
table.getActionMap().put(invertSelected, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
TableModel model = table.getModel();
for (int selectedRow : table.getSelectedRows()) {
var row = table.convertRowIndexToModel(selectedRow);
var value = !(Boolean) model.getValueAt(row, CHECKBOX_COL);
model.setValueAt(value, row, CHECKBOX_COL);
}
}
});
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
frame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
});
}
private static class MyModel extends DefaultTableModel {
public MyModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
@Override
public boolean isCellEditable(int row, int column) {
return column == CHECKBOX_COL;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return (columnIndex == CHECKBOX_COL ? Boolean.class : String.class);
}
}
}
It now works. Thank you, everyone
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论