Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

help with custom RowSorter for a JTable

843806Jun 2 2008 — edited Jun 3 2008
Hello all,
I am trying to add a custom row sorter to my project. When the user clicks to sort a table, i want it to actually sort the underlying list, not the view. I feel i have implemented this, following what the docs for RowSorter say for databases, and just make a RowSorter that interfaces with your database.
The problem is when i add my custom RowSorter, i get a NullPointerException way up in Suns code. And i dont have that source code or know how to get it to investigate what it is doing.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at sun.swing.table.DefaultTableCellHeaderRenderer.getTableCellRendererComponent(DefaultTableCellHeaderRenderer.java:69)

I have even tryed setting a DefaultRenderer for the Header (see line 81), but i still get the same exception.

I have made a short example app that will show you what im seeing.
Comment out line 77 and you will see it runs fine without the custom RowSorter.

Thanks for you help,
Will
// BEGIN CODE EXAMPLE
package test1;

import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.RowSorter;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.AbstractTableModel;

public class Main extends javax.swing.JFrame implements Runnable {

    private ArrayList<String> data = new ArrayList<String>();

    /** Creates new form Main */
    public Main() {
    }

    public static void main(String... args) {
        EventQueue.invokeLater(new Main());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jScrollPane1.setViewportView(jTable1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>
    public void run() {
        initComponents();

        // just filling my data list with random strings
        Random r = new Random();
        for (int i = 0; i < 20; ++i) {
            data.add(Integer.toHexString(r.nextInt()));
        }

        initMyTableStuff();

        this.setVisible(true);
    }

    private void initMyTableStuff() {
        jTable1.setModel(new MyTableModel());

        // the app runs just fine without the next line
        jTable1.setRowSorter(new MyRowSorter());

    // i dont think i should have to set a default header renderer, the docs
    // say that when its null it will use the default renderer.
    //jTable1.getColumnModel().getColumn(0).setHeaderRenderer(jTable1.getTableHeader().getDefaultRenderer());

    }

    private class MyRowSorter extends RowSorter<MyTableModel> {

        List<? extends SortKey> keys = null;

        @Override
        public Main.MyTableModel getModel() {
            return (MyTableModel) jTable1.getModel();
        }

        @Override
        public void toggleSortOrder(int column) {
            Collections.sort(data);
        }

        @Override
        public int convertRowIndexToModel(int index) {
            return index;
        }

        @Override
        public int convertRowIndexToView(int index) {
            return index;
        }

        @Override
        public void setSortKeys(List<? extends SortKey> keys) {
            this.keys = keys;
        }

        @Override
        public List<? extends SortKey> getSortKeys() {
            return keys;
        }

        @Override
        public int getViewRowCount() {
            return getModelRowCount();
        }

        @Override
        public int getModelRowCount() {
            return jTable1.getModel().getRowCount();
        }

        @Override
        public void modelStructureChanged() {
        }

        @Override
        public void allRowsChanged() {
        }

        @Override
        public void rowsInserted(int firstRow, int endRow) {
        }

        @Override
        public void rowsDeleted(int firstRow, int endRow) {
        }

        @Override
        public void rowsUpdated(int firstRow, int endRow) {
        }

        @Override
        public void rowsUpdated(int firstRow, int endRow, int column) {
        }
    }

    private class MyTableModel extends AbstractTableModel {

        public int getRowCount() {
            return data.size();
        }

        public int getColumnCount() {
            return 1;
        }

        public String getColumnName(int columnIndex) {
            return "DATA" + columnIndex;
        }

        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return data.get(rowIndex);
        }

        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            data.set(rowIndex, (String) aValue);
        }
    }
    // Variables declaration - do not modify
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration
}
// END OF CODE EXAMPLE
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 1 2008
Added on Jun 2 2008
2 comments
763 views