Wenn der Benutzer:
- die zweite Tabellenzeile auswählt.
- Smith in das Filterfeld eingibt und die Eingabetaste drückt.
Hier ist ein MRE. Es umfasst sowohl eine gute als auch eine schlechte Implementierung der Tabellenfülllogik.
Wenn Sie die gute Implementierung beibehalten, ist der Testfall bestanden.
Wenn Sie jedoch die schlechte Implementierung beibehalten, ist der Testfall fehlgeschlagen. Was es noch interessanter macht, ist, dass es erfolgreich ist, wenn Sie das Feld leeren, die Eingabetaste drücken und den Testfall wiederholen.
Code: Select all
package demos.table;
import javax.swing.DefaultRowSorter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.util.regex.Pattern;
public class SimpleTableDemo {
static JTable table;
private static JLabel tableLabel;
public static void main(String[] args) {
Container mainPanel = createMainPanel();
JFrame frame = new JFrame("Simple Table Demo");
frame.setContentPane(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static Container createMainPanel() {
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(createFilterField(), BorderLayout.NORTH);
mainPanel.add(createScroller());
mainPanel.add(createTableLabel(), BorderLayout.SOUTH);
return mainPanel;
}
private static Component createTableLabel() {
tableLabel = new JLabel(createTableLabelText());
return tableLabel;
}
private static Component createFilterField() {
JTextField field = new JTextField();
field.addActionListener(e -> onFilter(field));
return field;
}
private static void onFilter(JTextField field) {
DefaultRowSorter rowSorter = (DefaultRowSorter) table.getRowSorter();
String regex = String.format("(?i)%s", Pattern.quote(field.getText()));
rowSorter.setRowFilter(RowFilter.regexFilter(regex, 1, 2));
}
private static Component createScroller() {
JScrollPane scroller = new JScrollPane();
scroller.setViewportView(createTable());
return scroller;
}
private static Component createTable() {
table = new JTable();
table.setAutoCreateRowSorter(true);
fillTableGood();
// fillTableBad();
table.getSelectionModel().addListSelectionListener(e -> updateTableLabel());
return table;
}
/**
* Good implementation.
*/
private static void fillTableGood() {
DefaultTableModel model = new DefaultTableModel(createRows(), createColumns());
table.setModel(model);
}
private static String[][] createRows() {
return new String[][]{{"21", "Peter", "Smith"},
{"25", "Helen", "Brown"},
{"30", "Josh", "Brown"},
};
}
private static String[] createColumns() {
return new String[]{"Age", "First Name", "Last Name"};
}
/**
* Bad implementation.
*/
private static void fillTableBad() {
DefaultTableModel model = new DefaultTableModel();
table.setModel(model);
String[] columns = createColumns();
model.setColumnCount(columns.length);
model.setColumnIdentifiers(columns);
String[][] rows = createRows();
for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
String[] row = rows[rowIndex];
model.setRowCount(model.getRowCount() + 1);
for (int columnIndex = 0; columnIndex < row.length; columnIndex++) {
String cellData = row[columnIndex];
model.setValueAt(cellData, rowIndex, columnIndex);
}
}
}
private static void updateTableLabel() {
String text = createTableLabelText();
if (tableLabel != null) tableLabel.setText(text);
}
private static String createTableLabelText() {
int rowCount = table.getRowCount();
String text = String.format("Rows: %d", rowCount);
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) text = String.format("Row %d from %d", selectedRow + 1, rowCount);
return text;
}
}
Code: Select all
// initializes lastModelSelection — bad!
private void cacheModelSelection(RowSorterEvent sortEvent) {
lastModelSelection = convertSelectionToModel(sortEvent);
modelLeadIndex = convertRowIndexToModel(sortEvent,
selectionModel.getLeadSelectionIndex());
}
Code: Select all
// the second if branch is a good one, the execution should go there
private void restoreSelection(ModelChange change) {
syncingSelection = true;
if (lastModelSelection != null) {
restoreSortingSelection(lastModelSelection,
modelLeadIndex, change);
lastModelSelection = null;
} else if (modelSelection != null) {
Was sind die Hauptursachen für dieses Verhalten und gibt es irgendwelche Optimierungen an der „schlechten“ Implementierung, die dafür sorgen würden, dass es funktioniert?
Java 8.
Mobile version