#java #sorting #jtable #glazedlists #jxtable
#java #сортировка #jtable #закрытые списки #jxtable
Вопрос:
Я использую закрытые списки для сортировки и фильтрации JXTable.
Как я могу выполнить сортировку по значениям вне таблицы? То есть я хотел бы иметь возможность форматировать значения столбцов по-своему, но сортировать по необработанным значениям.
Мой текущий соответствующий код:
EventList<Foo> foos = GlazedLists.threadSafeList(new BasicEventList<Foo>());
foos.add(new Foo("bar", 5000000));
ObservableElementList.Connector<Foo> fooConnector = GlazedLists.beanConnector(Foo.class);
EventList<Foo> observedFoos = new ObservableElementList<Foo>(foos, fooConnector);
SortedList<Foo> sortedFoos = new SortedList<Foo>(observedFoos, null);
EventTableModel tableModel = new EventTableModel(sortedFoos, someTableFormat);
JXTable t = new JXTable(tableModel);
new TableComparatorChooser<Foo>(t, sortedFoos, false);
В этом примере я хотел бы отформатировать значение во втором столбце как, 5.0M
а не 5000000
как, но если я использую это значение в списке, оно не будет отсортировано должным образом.
Заранее спасибо.
Ответ №1:
Может быть, вам нужно отключить сортировку JXTable, чтобы она не мешала сортировке GL? Что-то вроде:
jxtable.setSortable(false);
jxtable.setAutoCreateRowSorter(false);
jxtable.setRowSorter(null);
… а затем установите GlazedLists TableComparatorChooser в таблицу следующим образом:
TableComparatorChooser.install(jxtable, sortedFoos, TableComparatorChooser.SINGLE_COLUMN);
Или вы имеете в виду, что вы хотите отформатировать 5000000 как 5.0M в таблице, а не в списке? Тогда вам нужно было бы только реализовать ваш TableFormat в
public Object getColumnValue(E yourObject, int column)
чтобы вернуть 5.0-миллионное представление 5000000.
… вполне может быть, что я не до конца понял проблему, и эти ответы не помогают 😉
РЕДАКТИРОВАТЬ: Доступный для выполнения пример…
Посмотрите на код в методе main — особенно на код с комментарием от НАЧАЛА до КОНЦА. Я создал свой собственный очень простой пример, но вы должны понять, что я имею в виду.
О … извините за присвоение имен классам / переменным / … 😉
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.EventTableModel;
import ca.odell.glazedlists.swing.TableComparatorChooser;
import java.util.Comparator;
import java.util.List;
import javax.swing.ComboBoxEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import org.jdesktop.swingx.JXTable;
public class Tester {
private static class MyObject implements Comparable<MyObject> {
private final int number;
private final String value;
public MyObject(int number, String value) {
this.number = number;
this.value = value;
}
public int getNumber() {
return number;
}
public String getValue() {
return value;
}
@Override
public int compareTo(MyObject t) {
return value.compareTo(t.getValue());
}
}
private static class MyTableFormat implements TableFormat<MyObject> {
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int i) {
switch (i) {
case 0:
return "FormattedNumber";
case 1:
return "String";
default:
throw new IllegalStateException();
}
}
@Override
public Object getColumnValue(MyObject e, int i) {
switch (i) {
case 0:
return getNumberString(e.getNumber());
case 1:
return e.getValue();
default:
throw new IllegalStateException();
}
}
private Object getNumberString(int number) {
switch (number) {
case 1:
return "One";
case 2:
return "Two";
case 3:
return "Three";
default:
throw new IllegalStateException();
}
}
}
private static class MyComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject t, MyObject t1) {
return Integer.valueOf(t.getNumber()).compareTo(Integer.valueOf(t1.getNumber()));
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
EventList<MyObject> list = new BasicEventList<MyObject>();
list.add(new MyObject(1, "A"));
list.add(new MyObject(2, "B"));
list.add(new MyObject(3, "C"));
SortedList<MyObject> sortedList = new SortedList<MyObject>(list);
EventTableModel<MyObject> tableModel = new EventTableModel<MyObject>(sortedList, new MyTableFormat());
JXTable jxtable = new JXTable(tableModel);
/**
* START
* - Deactivate JXTables build-in sorting
* - Install GlazedLists sorting
* - Set the comparator for the "string number" column
*/
// deactivate sorting of JXTable
jxtable.setSortable(false);
jxtable.setAutoCreateRowSorter(false);
jxtable.setRowSorter(null);
// enable GlazedLists sorting
TableComparatorChooser<MyObject> tcc = TableComparatorChooser.install(jxtable, sortedList, TableComparatorChooser.SINGLE_COLUMN);
// set the comparator for your "string number" column
List<Comparator> comparators = tcc.getComparatorsForColumn(0);
comparators.clear();
comparators.add(new MyComparator());
/**
* END
*/
JFrame f = new JFrame("Tester");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(jxtable));
f.pack();
f.setVisible(true);
}
}
Комментарии:
1. Спасибо за ответ, Кай. Это второй вариант, которого я пытаюсь достичь. Я попытался
getColumnValue(Object baseObject, int column)
отформатировать значение как 5.0M, но тогда оно не будет отсортировано должным образом, поскольку я форматирую 5.0M как строку. Похоже, что сортировка основана наgetColumnValue(Object baseObject, int column)
, а не на исходном списке.2. Вы пытались переключить механизм сортировки JXTable, а затем установить механизм сортировки закрытых списков (TableComparatorChooser)? Возможно, что при щелчке по заголовку таблицы вы запускаете сортировку JXTable вместо сортировки GlazedLists…
3. Большое спасибо Каю за этот очень полный ответ. Проблема заключалась в том, что я не вызывал
comparators.clear()
перед добавлением моего компаратора. Определить это по моему первоначальному вопросу было невозможно, поэтому хорошо сделано 🙂 Надеюсь, другие найдут ваш ответ в будущем. Еще раз спасибо.