0

I would like to include glazedlists in an existing project that uses JTables and JXTables. Mainly because of the easier event-handling. I have made a view tests and came across a problem when exchanging the complete list content. I do this by calling

eventList.clear();
eventList.addAll(...);

The error happens only, if the standard table sorting of JTable is activated.

There are a lot of hints around this topic in the net, but I do not get the glue on what the problem here is. Is it at least, that glazedlists does not work together with the standard JTable sorting? I am using java7, glazedLists 1.9.0 , example code is:

package poc;

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.swing.AdvancedTableModel;
import ca.odell.glazedlists.swing.GlazedListsSwing;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

/**
 * TestGlazedLists
 *
 */
public class TestGlazedLists {

    public static class Person implements Comparable<Person>{
        private String name;
        private String surname;

        public Person(String name, String surname) {
            this.name = name;
            this.surname = surname;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getSurname() {
            return surname;
        }
        public void setSurname(String surname) {
            this.surname = surname;
        }

        @Override
        public int compareTo(Person o) {
            return this.getName().compareTo(o.getName());
        }
    }

    private BasicEventList eventList = new BasicEventList();
    private SortedList sortedList = new SortedList(eventList);

    private java.util.List<Person> createList() {
        ArrayList<Person> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add(new Person("James" + i, "Bond" + i));
        }
        return list;
    }

    public TestGlazedLists() {
    }

    public static void main(String[] args) {
        new TestGlazedLists().openDialog();
    }

    private void openDialog() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAll();
            }
        });
    }

    public void initAll() {
        JDialog d = new JDialog();
        d.setLayout(new BorderLayout());
        JButton refreshB = new JButton("refresh");
        d.add(refreshB, BorderLayout.NORTH);
        refreshB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                refreshList();
            }
        });
        JTable t = new JTable();
        t.setAutoCreateRowSorter(true);

        d.add(new JScrollPane(t), BorderLayout.CENTER);

        String[] propertyNames = {"name", "surname"};
        String[] columnLabels = {"name", "surname"};
        boolean[] writable = {false, false};

        AdvancedTableModel<Person> model = GlazedListsSwing.eventTableModel(eventList, propertyNames, columnLabels, writable);
        t.setModel(model);

        //TableFormat tableFormat = GlazedLists.tableFormat(propertyNames, columnLabels, writable);
        //JXTableSupport.install(t, eventList, tableFormat, sortedList, AbstractTableComparatorChooser.MULTIPLE_COLUMN_MOUSE);

        d.setPreferredSize(new Dimension(500, 300));
        d.pack();
        d.setVisible(true);
    }

    public void refreshList() {
        eventList.clear();
        eventList.addAll(createList());
    }
}

Klicking a first time "refresh" works, clicking a second time crashes with

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid range
    at javax.swing.DefaultRowSorter.rowsDeleted(DefaultRowSorter.java:880)
    at javax.swing.JTable.notifySorter(JTable.java:4273)
    at javax.swing.JTable.sortedTableChanged(JTable.java:4117)
    at javax.swing.JTable.tableChanged(JTable.java:4394)
    at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
    at ca.odell.glazedlists.swing.DefaultEventTableModel.handleListChange(DefaultEventTableModel.java:140)
    at ca.odell.glazedlists.swing.DefaultEventTableModel.listChanged(DefaultEventTableModel.java:118)
    at ca.odell.glazedlists.event.ListEventAssembler$ListEventFormat.fire(ListEventAssembler.java:424)
    at ca.odell.glazedlists.event.ListEventAssembler$ListEventFormat.fire(ListEventAssembler.java:421)
    at ca.odell.glazedlists.event.SequenceDependenciesEventPublisher$SubjectAndListener.firePendingEvent(SequenceDependenciesEventPublisher.java:445)
    at ca.odell.glazedlists.event.SequenceDependenciesEventPublisher.fireEvent(SequenceDependenciesEventPublisher.java:344)
    at ca.odell.glazedlists.event.ListEventAssembler.commitEvent(ListEventAssembler.java:317)
    at ca.odell.glazedlists.BasicEventList.clear(BasicEventList.java:206)

I have also tried variations with JXTable, but the result is identical.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
langm
  • 171
  • 7

1 Answers1

1

Let GlazedLists handle the JTable sorting for you.

Step 1: remove/comment out the auto row sorter line:

t.setAutoCreateRowSorter(true); // remove me: I interfere with GlazedLists

Step two: use the sorted event list in your model rather than the basic:

AdvancedTableModel<Person> model = GlazedListsSwing.eventTableModel(sortedList, propertyNames, columnLabels, writable);

Step three: install GlazedLists TableComparitorChooser to your JTable, which adds row sorting capabilities to the JTable:

TableComparatorChooser<Person> tableSorter = TableComparatorChooser.install(
        t, sortedList, TableComparatorChooser.SINGLE_COLUMN);

You should now find everything works when you refresh. Clicking the column headings will enable column sorting. You can play around with some of the options for the TableComparitorChooser if you don't like the way it does multi-column sorting.

andyroberts
  • 3,458
  • 2
  • 37
  • 40
  • This does not work for me: it sorts only by my defined comparator! Clicking on another column does not order by that column! Anyway, I would more like to have the standard JTable sorting working. So do I need to accept that glazedLists are not compatible with the JTable´s standard sorting mechanism? – langm Jun 01 '13 at 15:35
  • @langm I've updated the example to use SINGLE_COLUMN rather than MULTIPLE_COLUMN_MOUSE because the latter isn't actually all intuitive; SINGLE_COLUMN should act as you'd expect. One of the core features of GlazedLists was to provide advanced sorting and filtering to JTables well before such features existed in Swing. The eventList is so powerful - and other GL associated utilties - that it's worth considering whether sticking to JTable's built in sorting is better than what GlazedLists can offer. – andyroberts Jun 02 '13 at 15:59