Sto provando a creare un filtro Row per un JTable per limitare il numero di righe visualizzate nella tabella.Come funziona JTable RowFilter?
Il codice RowFilter è semplice. Si converte il numero di modello fila al numero fila vista (nel caso la tabella è ordinata) e quindi controlla se il numero di vista fila è meno che il numero di linee da visualizzare nella tabella:
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;
}
};
Il problema è che il numero di riga del modello non viene sempre convertito in un numero di riga di vista ragionevole in modo che troppe righe vengano incluse nel filtro. Per dimostrare eseguire il codice qui sotto:
1) Selezionare "1" dalla casella combinata e si otterrà un output simile:
Change the Filter to: 1
m0 : v0
m1 : v0
m2 : v0
m3 : v0
m4 : v0
Questa uscita mi sta dicendo che tutte le righe del modello vengono convertiti per visualizzare fila 0. Poiché 0 è inferiore al valore del filtro 1, tutte le righe sono incluse nel filtro (che è errato).
Quindi la domanda qui è perché lo convertRowIndexToView(modelRow)
non funziona come previsto?
2) Ora selezionate "2" dalla casella combinata e si otterrà un output simile:
Change the Filter to: 2
m0 : v0
m1 : v1
m2 : v2
m3 : v3
m4 : v4
Come si può vedere le righe del modello sono ora mappatura per la corretta fila di vista, in modo che solo 2 di fila sono incluso nel filtro che è corretto.
3) Ora selezionate "3" dalla casella combinata e si otterrà un output simile:
Change the Filter to: 3
m0 : v0
m1 : v1
m2 : v-1
m3 : v-1
m4 : v-1
In questo caso le ultime 3 file modello vengono convertiti in -1, che presumo significa che la riga è non attualmente visibile nella tabella, che è corretto. Quindi in questo caso tutte le 5 righe sono di nuovo incluse nel filtro che non è corretto poiché vogliamo solo il primo 3.
Quindi la domanda qui è come reimpostare il filtro in modo che tutte le righe del modello siano mappate alla riga di visualizzazione originale?
Ho cercato di utilizzare:
((TableRowSorter) table.getRowSorter()).setRowFilter(null);
((TableRowSorter) table.getRowSorter()).setRowFilter(filter);
per cancellare il filtro, prima di ripristinare il filtro, ma questo ha dato gli stessi risultati come passaggio 1. Cioè, adesso tutti righe modello mappa per visualizzare riga 0 (così tutte e 5 le righe sono ancora visualizzate).
Ecco il codice di prova:
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();
}
});
}
}
Qualsiasi idea di come creare un filtro di riga per visualizzare le prime file "n"?
Oh sì, un altro punto frustrante. Se rimuovi il commento dalle due righe System.out .. nel metodo actionPeformed(), quando selezioni 1 dalla casella combinata noterai che in entrambi i casi l'indice del modello 4 viene convertito per visualizzare l'indice 4 e queste due uscite sono racchiuse tra loro il modello errato per visualizzare le conversioni ???
Edit:
Sulla base di MadProgrammers suggerimento che ho provato:
//((TableRowSorter) table.getRowSorter()).setRowFilter(filter);
TableRowSorter sorter = new TableRowSorter();
table.setRowSorter(sorter);
sorter.setRowFilter(filter);
sorter.sort();
Ora ho nulla nella tabella.
"Guess" è che si tratta di "alcune volte" che lavorano con i dati precedentemente filtrati set. .. – MadProgrammer
Ho finito per creare un nuovo 'TableRowSorter', applicandolo a' JTable' impostando 'rowFilter' su quel sorter e poi chiamando' sort' su 'TableRowSorter' ...: P – MadProgrammer
@MadProgrammer,'. ... set di dati precedentemente filtrati sì e immagino che la domanda sia: perché? Immagino che la maggior parte dei filtri si basino sui dati effettivi nel TableModel, quindi questo non è un problema dato che la mappatura degli indici sarà rifatta dopo il filtro? 'Ho finito per creare ...' - non ha funzionato per me. Suppongo che ho fatto qualcos'altro di sbagliato? – camickr