Ich habe eine JTable, die eine Spalte mit Text enthält, die nicht bearbeitet werden kann, und die zweite Spalte ist ein Kontrollkästchen, das boolesche Werte anzeigt …. Jetzt möchte ich, wenn der Benutzer mehrere Zeilen auswählt und eine der aktivierte Kontrollkästchen, dann sollten alle Kontrollkästchen unter Auswahl deaktiviert werden und umgekehrt.
Mehrfache Zeilenauswahl in JTable
Sasidhar
Müllgott
Unter Verwendung des Beispiels von @Hovercraft und der Ratschläge von @camickr zeigt das folgende Beispiel eine geeignete Benutzeroberfläche. Obwohl es Schaltflächen verwendet, die SelectionAction
wäre auch für ein Menü oder Popup geeignet.
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();
}
});
}
}
-
-
Hallo, es tut mir leid, dass ich antworte, aber ich habe dies erst vor einer Weile gefunden und hätte gerne einen Beitrag zum Hinzufügen eines Listeners für Änderungen in der Liste. Im Moment verwende ich einen mouseListener, aber er wird ausgelöst, bevor die Liste tatsächlich aktualisiert wird. Wie kann ich einen Listener hinzufügen, um Aktualisierungen für die Liste zu erhalten, sobald sie auftreten?
– Sam
15. April 2014 um 14:00 Uhr
-
Vielleicht ein
TableCellEditor
hier gesehen?– Müllgott
15. April 2014 um 14:03 Uhr
Das Problem besteht darin, dass die Auswahl aller Zeilen verloren geht, wenn Sie auf ein Kontrollkästchen klicken, um den Wert des Kontrollkästchens zu ändern. Daher müssen Sie möglicherweise mit der rechten Maustaste klicken, um ein Popup-Menü anzuzeigen, das Werte zum Auswählen/Abwählen enthält.
Dann können Sie table.getSelectedRows() verwenden, um die Indizes aller ausgewählten Zeilen zu erhalten, die Sie aktualisieren müssen.
-
Sie haben Recht …. wenn jemals auf das Kontrollkästchen geklickt wird, geht die gesamte Zeilenauswahl verloren … gibt es eine Möglichkeit, dies zu umgehen, ohne den Rechtsklick zu verwenden …?
– Sasidhar
24. Dezember 2010 um 16:37 Uhr
-
Sie können einen Mausklick nicht für zwei verschiedene Funktionen verwenden. Die Lösung ist eine richtige Benutzeroberfläche. Ich habe einen Vorschlag gemacht, ein Popup-Menü zu verwenden. Eine andere Lösung besteht darin, menuItems aus einem Menü mit Zugriffstasten zum Auswählen/Abwählen zu verwenden. Auf diese Weise kann der Benutzer die Maus oder die Tastatur verwenden. Oder Sie können der Benutzeroberfläche Schaltflächen hinzufügen, um dasselbe zu tun.
– camickr
24. Dezember 2010 um 18:24 Uhr
-
Ich muss @camickr zustimmen; Ich habe ein Beispiel in der Nähe hinzugefügt.
– Müllgott
24. Dezember 2010 um 22:48 Uhr
Sie können das Auswahlintervall mit einem ähnlichen Code wie diesem erhalten:
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
minSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMinSelectionIndex();
maxSelectedRow = ((DefaultListSelectionModel)e.getSource()).getMaxSelectionIndex();
}
});
Wenn dann ein Kontrollkästchen aktiviert ist (listen to ItemEvent
) sollten Sie von iterieren minSelectedRow
zum maxSelectedRow
und ändern Sie den Zustand der aktivierten Kästchen. Das ist es.
Hovercraft voller Aale
Ich stimme Roman zu, dass seine Idee funktionieren würde, wenn Sie ein Klassenfeld verwenden, um die Min- und Max-Auswahl zu speichern. Zum Beispiel:
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();
}
});
}
}