Ich versuche, einen Zeilenfilter für eine JTable zu erstellen, um die Anzahl der in der Tabelle angezeigten Zeilen zu begrenzen.Wie funktioniert JTable RowFilter?
Der RowFilter-Code ist einfach. Er wandelt die Modellreihennummer zu der Ansicht Zeilennummer (falls die Tabelle sortiert wird), und dann prüft, ob die Ansicht Zeilennummer kleiner ist, dass die Anzahl der Zeilen in der Tabelle angezeigt werden:
RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>()
{
@Override
public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry)
{
int modelRow = entry.getIdentifier();
int viewRow = table.convertRowIndexToView(modelRow);
return viewRow < numberOfRows;
}
};
Das Problem
ist, dass die Modellreihennummer nicht immer in eine vernünftige Ansichtszeilennummer umgewandelt wird, so dass zu viele Zeilen in dem Filter enthalten sind. Um zu demonstrieren, führen Sie den Code unten:1) Wählen Sie „1“ aus dem Kombinationsfeld ein und Sie erhalten eine Ausgabe wie:
Change the Filter to: 1
m0 : v0
m1 : v0
m2 : v0
m3 : v0
m4 : v0
Dieser Ausgang sagt mir, dass alle Modellreihen umgewandelt werden Zeile anzuzeigen 0. Da 0 kleiner als der Filterwert von 1 ist, sind alle Zeilen im Filter enthalten (was falsch ist).
Also die Frage ist, warum funktioniert die convertRowIndexToView(modelRow)
nicht wie erwartet?
2) Wählen Sie nun „2“ aus dem Kombinationsfeld, und Sie werden eine Ausgabe wie erhalten:
Change the Filter to: 2
m0 : v0
m1 : v1
m2 : v2
m3 : v3
m4 : v4
Wie Sie die Modellreihen werden nun auf die richtige Ansicht Reihe, so dass nur 2 row Abbildung zu sehen sind im richtigen Filter enthalten.
3) Wählen Sie nun „3“ aus der Box Combo und Sie werden eine Ausgabe wie erhalten:
Change the Filter to: 3
m0 : v0
m1 : v1
m2 : v-1
m3 : v-1
m4 : v-1
In diesem Fall sind die letzten drei Modellreihen auf -1 umgewandelt werden, die ich übernehmen bedeutet, dass die Zeile momentan nicht sichtbar in der Tabelle, was korrekt ist. Also in diesem Fall sind alle 5 Zeilen wieder im Filter enthalten, was falsch ist, da wir nur die ersten 3 wollen.
Also ist die Frage hier, wie man den Filter zurücksetzt, so dass alle Modellreihen der ursprünglichen Ansichtsreihe zugeordnet werden?
Ich habe versucht, zu verwenden:
((TableRowSorter) table.getRowSorter()).setRowFilter(null);
((TableRowSorter) table.getRowSorter()).setRowFilter(filter);
den Filter zu löschen, bevor Sie den Filter zurückzusetzen, aber das ergab die gleichen Ergebnisse wie in Schritt 1. Das ist alles, jetzt die Modellreihen Zeile 0 sehen Karte (so alle 5 Zeilen werden noch angezeigt). Hier
ist der Testcode:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class FilterSSCCE extends JPanel
{
private JTable table;
public FilterSSCCE()
{
setLayout(new BorderLayout());
JComboBox<Integer> comboBox = new JComboBox<Integer>();
comboBox.addItem(new Integer(1));
comboBox.addItem(new Integer(2));
comboBox.addItem(new Integer(3));
comboBox.addItem(new Integer(4));
comboBox.addItem(new Integer(5));
comboBox.setSelectedIndex(4);
comboBox.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
//System.out.println(table.convertRowIndexToView(4));
Integer value = (Integer)comboBox.getSelectedItem();
newFilter(value);
//System.out.println(table.convertRowIndexToView(4));
}
});
add(comboBox, BorderLayout.NORTH);
table = new JTable(5, 1);
for (int i = 0; i < table.getRowCount(); i++)
table.setValueAt(String.valueOf(i+1), i, 0);
table.setAutoCreateRowSorter(true);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
}
private void newFilter(int numberOfRows)
{
System.out.println("Change the Filter to: " + numberOfRows);
RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>()
{
@Override
public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry)
{
int modelRow = entry.getIdentifier();
int viewRow = table.convertRowIndexToView(modelRow);
System.out.println("m" + modelRow + " : v" + viewRow);
return viewRow < numberOfRows;
}
};
((TableRowSorter) table.getRowSorter()).setRowFilter(filter);
}
private static void createAndShowGUI()
{
JPanel panel = new JPanel();
JFrame frame = new JFrame("FilterSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FilterSSCCE());
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Jede Idee, wie ein Zeilenfilter erstellen, um die ersten „n“ Zeilen angezeigt werden?
Oh ja, noch ein frustrierender Punkt. Wenn Sie die beiden Zeilen System.out .. in der actionPeformed() -Methode auskommentieren, werden Sie bei der Auswahl von 1 aus dem Kombinationsfeld feststellen, dass in beiden Fällen der Modellindex 4 in Ansichtsindex 4 konvertiert wird und diese beiden Ausgaben umschlossen sind das falsche Modell zum Anzeigen von Conversions?
Edit:
Basierend auf MadProgrammers Vorschlag habe ich versucht:
//((TableRowSorter) table.getRowSorter()).setRowFilter(filter);
TableRowSorter sorter = new TableRowSorter();
table.setRowSorter(sorter);
sorter.setRowFilter(filter);
sorter.sort();
Jetzt nichts in der Tabelle I erhalten.
„Vermutung“ ist, dass es „einige Male“ die Arbeit mit den zuvor eingestellten gefilterten Daten. .. – MadProgrammer
Ich habe am Ende einen neuen 'TableRowSorter' erstellt, den auf' JTable' angewendet, den 'rowFilter' auf diesen Sortierer gesetzt und dann' sort' auf dem 'TableRowSorter' aufgerufen ...: P – MadProgrammer
@MadProgrammer,'. ..vorher gefilterter Datensatz ja und ich denke die Frage ist warum? Ich schätze, die meisten Filter basieren auf den tatsächlichen Daten im TableModel, also ist das kein Problem, da das Mapping der Indizes nach der Filterung noch einmal durchgeführt wird. 'Ich endete am Erstellen ...' - hat nicht für mich gearbeitet. Schätze, ich habe etwas anderes falsch gemacht? – camickr