Search code examples
javaswingjtabledefaulttablemodelrowfilter

Get topX elements in JTable


I have a JTable that is sortable by the column headers:

enter image description here

I would now like to only display the X first rows in the table. Have understood that the table sorting is not in the tableModel. I thought it would be a good idea to copy the JTable data to the Model and then just retrieve the first X elements. But it seems to fail. Any idea how to solve this task?

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class SortJTable {

    public static void main(String[] args) {
        final String[] columns = getTableColumns();
        final Object[][] tableData = getTableValues();
        TableModel model = new DefaultTableModel(tableData, columns);

        final JTable table = new JTable(model);
        table.setAutoCreateRowSorter(true); // Make it possible to column-sort

        final JComboBox<String> box = new JComboBox<String>();
        box.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {

                // TRY TO SORT THE MODEL AS THE TABLE
                for(int i=0; i<10; i++)
                    table.convertColumnIndexToModel(i);

                // IF MODEL IS SORTED AS TABLE: TAKE WANTED ELEMENTS
                Object[][] newModel;
                if(box.getSelectedIndex() == 0){
                    System.out.println("SHOW ALL");
                }
                else if(box.getSelectedIndex() == 1){
                    System.out.println("SHOW 5");

                    // CREATE NEW MODEL WITH ONLY 5 FIRST ELEMENTS FROM THE SORTED MODEL
                    newModel = new Object[5][10];
                    for(int col=0; col<tableData[0].length; col++){
                        for(int row=0; row<5; row++){
                            newModel[row][col] = tableData[row][col];

                            TableModel model = new DefaultTableModel(tableData, columns);
                            table.setModel(model);
                        }
                    }
                }
                else{
                    System.out.println("SHOW 10");
                }
            }
        });
        box.addItem("Show all rows");
        box.addItem("Show 5 first rows");
        box.addItem("Show 10 first rows");

        JPanel content = new JPanel();
        content.add(new JScrollPane(table));
        content.add(box);

        JFrame frame = new JFrame();
        frame.add(content);
        frame.pack();
        frame.setVisible(true);
    }

    private static String[] getTableColumns(){
        String[] columns = new String[10];
        for(int i=0; i<10; i++)
            columns[i] = "col"+i;
        return columns;
    }

    private static Object[][] getTableValues(){
        Object[][] tableData = new Object[10][10];
        for(int i=0; i<tableData.length; i++){
            for(int j=0; j<tableData[0].length; j++){
                tableData[i][j] = i+""+j;
            }
        }
        return tableData;
    }
}

Solution

  • This approach overrides the getRowCount() method of the JTable:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.table.*;
    
    public class SortJTable {
    
        public static void main(String[] args) {
            final String[] columns = getTableColumns();
            final Object[][] tableData = getTableValues();
            TableModel model = new DefaultTableModel(tableData, columns);
    
            final JTable table = new JTable(model)
            {
                @Override
                public int getRowCount()
                {
                    int rows = (int)getClientProperty("rows");
    
                    if (rows == -1)
                        return getModel().getRowCount();
                    else
                        return rows;
                }
            };
            table.setAutoCreateRowSorter(true); // Make it possible to column-sort
    
            final JComboBox<String> box = new JComboBox<String>();
            box.addActionListener(new ActionListener(){
    
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    if(box.getSelectedIndex() == 0)
                    {
                        System.out.println("SHOW ALL");
                        table.putClientProperty("rows", new Integer(-1));
                    }
                    else if(box.getSelectedIndex() == 1)
                    {
                        System.out.println("SHOW 5");
                        table.putClientProperty("rows", new Integer(5));
    
                    }
                    else
                    {
                        System.out.println("SHOW 7");
                        table.putClientProperty("rows", new Integer(7));
                    }
    
                    table.revalidate();
                    table.repaint();
                }
            });
            box.addItem("Show all rows");
            box.addItem("Show 5 first rows");
            box.addItem("Show 7 first rows");
    
            JFrame frame = new JFrame();
            frame.add(new JScrollPane(table));
            frame.add(box, BorderLayout.SOUTH);
            frame.pack();
            frame.setVisible(true);
        }
    
        private static String[] getTableColumns(){
            String[] columns = new String[10];
            for(int i=0; i<10; i++)
                columns[i] = "col"+i;
            return columns;
        }
    
        private static Object[][] getTableValues(){
            Object[][] tableData = new Object[10][10];
            for(int i=0; i<tableData.length; i++){
                for(int j=0; j<tableData[0].length; j++){
                    tableData[i][j] = i+""+j;
                }
            }
            return tableData;
        }
    }