我有一个JTable,它有一列是不可编辑的文本,第二列是一个显示布尔值的复选框....现在我想要的是,当用户选择多行并取消选中任何一行时其中一个选中的复选框,然后选中的所有复选框都应取消选中,反之亦然。
答案 0 :(得分:14)
使用@ Hovercraft的示例和@ camickr的建议,下面的示例显示了一个合适的用户界面。虽然它使用按钮,但SelectionAction
也适用于菜单或弹出窗口。
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.DefaultListSelectionModel;
import javax.swing.table.DefaultTableModel;
/** @see http://stackoverflow.com/questions/4526779 */
public class CheckABunch extends JPanel {
private static final int CHECK_COL = 1;
private static final Object[][] DATA = {
{"One", Boolean.TRUE}, {"Two", Boolean.FALSE},
{"Three", Boolean.TRUE}, {"Four", Boolean.FALSE},
{"Five", Boolean.TRUE}, {"Six", Boolean.FALSE},
{"Seven", Boolean.TRUE}, {"Eight", Boolean.FALSE},
{"Nine", Boolean.TRUE}, {"Ten", Boolean.FALSE}};
private static final String[] COLUMNS = {"Number", "CheckBox"};
private DataModel dataModel = new DataModel(DATA, COLUMNS);
private JTable table = new JTable(dataModel);
private DefaultListSelectionModel selectionModel;
public CheckABunch() {
super(new BorderLayout());
this.add(new JScrollPane(table));
this.add(new ControlPanel(), BorderLayout.SOUTH);
table.setPreferredScrollableViewportSize(new Dimension(250, 175));
selectionModel = (DefaultListSelectionModel) table.getSelectionModel();
}
private class DataModel extends DefaultTableModel {
public DataModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == CHECK_COL) {
return getValueAt(0, CHECK_COL).getClass();
}
return super.getColumnClass(columnIndex);
}
@Override
public boolean isCellEditable(int row, int column) {
return column == CHECK_COL;
}
}
private class ControlPanel extends JPanel {
public ControlPanel() {
this.add(new JLabel("Selection:"));
this.add(new JButton(new SelectionAction("Clear", false)));
this.add(new JButton(new SelectionAction("Check", true)));
}
}
private class SelectionAction extends AbstractAction {
boolean value;
public SelectionAction(String name, boolean value) {
super(name);
this.value = value;
}
@Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < dataModel.getRowCount(); i++) {
if (selectionModel.isSelectedIndex(i)) {
dataModel.setValueAt(value, i, CHECK_COL);
}
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("CheckABunch");
frame.add(new CheckABunch());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowUI();
}
});
}
}
答案 1 :(得分:4)
问题是,当您单击复选框以更改复选框的值时,将丢失所有行的选择。因此,您可能需要使用鼠标右键单击以显示包含选择/取消选择值的弹出菜单。
然后您可以使用table.getSelectedRows()来获取需要更新的所有选定行的索引。
答案 2 :(得分:2)
您可以使用与此类似的代码获取选择间隔:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
minSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMinSelectionIndex();
maxSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMaxSelectionIndex();
}
});
然后,当选中一个复选框(收听ItemEvent
)时,您应该从minSelectedRow
迭代到maxSelectedRow
并更改选中的复选框状态。就是这样。
答案 3 :(得分:2)
我同意Roman的观点,如果你使用一个类字段来保存最小和最大选择,他的想法就会起作用。例如:
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
public class CheckABunch extends JPanel {
private static final Object[][] DATA = {{"One", Boolean.TRUE}, {"Two", Boolean.FALSE},
{"Three", Boolean.TRUE}, {"Four", Boolean.FALSE}, {"Five", Boolean.TRUE},
{"Six", Boolean.FALSE}, {"Seven", Boolean.TRUE}, {"Eight", Boolean.FALSE}};
private static final String[] COLUMNS = {"Number", "CheckBox"};
private DefaultTableModel model = new DefaultTableModel(DATA, COLUMNS) {
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 1) {
return getValueAt(0, 1).getClass();
}
return super.getColumnClass(columnIndex);
}
};
private JTable table = new JTable(model);
private int minSelectedRow = -1;
private int maxSelectedRow = -1;
boolean tableModelListenerIsChanging = false;
public CheckABunch() {
add(new JScrollPane(table));
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
minSelectedRow = ((DefaultListSelectionModel) e.getSource()).getMinSelectionIndex();
maxSelectedRow = ((DefaultListSelectionModel) e.getSource()).getMaxSelectionIndex();
}
});
model.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
if (tableModelListenerIsChanging) {
return;
}
int firstRow = e.getFirstRow();
int column = e.getColumn();
if (column != 1 || maxSelectedRow == -1 || minSelectedRow == -1) {
return;
}
tableModelListenerIsChanging = true;
boolean value = ((Boolean)model.getValueAt(firstRow, column)).booleanValue();
for (int i = minSelectedRow; i <= maxSelectedRow; i++) {
model.setValueAt(Boolean.valueOf(value), i, column);
}
// *** edit: added two lines
minSelectedRow = -1;
maxSelectedRow = -1;
tableModelListenerIsChanging = false;
}
});
}
private static void createAndShowUI() {
JFrame frame = new JFrame("CheckABunch");
frame.getContentPane().add(new CheckABunch());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}