TableRowSorter返回错误的SortOrder

时间:2016-07-20 20:55:21

标签: java sorting tablerowsorter

我制作了一个TableRowSorter,它应该更新每个列从ASCENDING => DESCENDING => ASCENDING => DESCENDING => ...ASCENDING => DESCENDING => UNSORTED => ASCENDING => DESCENDING => UNSORTED => ...

的排序周期
import java.util.ArrayList;
import java.util.List;

import javax.swing.SortOrder;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class ADU_SortOrder<M extends TableModel> extends TableRowSorter<M> {

    public ADU_SortOrder(M model) {
        setModel(model);
    }

    @Override
    public void toggleSortOrder(int column) {
        List<? extends SortKey> sortKeys = getSortKeys();
        if (sortKeys.size() > 0) {
            List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
            keys.set(0, new SortKey(column, setNextOrder(sortKeys.get(0).getSortOrder())));
            setSortKeys(keys);
            return;
        }
        super.toggleSortOrder(column);
    }

    private SortOrder setNextOrder(SortOrder order) {
        switch (order) {
            case ASCENDING:
                return SortOrder.DESCENDING;
            case DESCENDING:
                return SortOrder.UNSORTED;
            case UNSORTED:
                return SortOrder.ASCENDING;
            default:
                return SortOrder.UNSORTED;
        }
    }
}

在给定的例子中,我将尝试描述我期望发生的事情以及实际发生的事情。您有一个JTable,其中包含两列。在开始时使用的SortKeys使得每列中的最后一个排序都是SortOrder.ASCENDING

我期望在这里发生的事情如下:

Sort Order in: Column 1           Column 2
Start:        ASCENDING           ASCENDING
Click C1:     DESCENDING          ASCENDING
Click C1:      UNSORTED           ASCENDING
Click C2:      UNSORTED          DESCENDING
Click C1:     ASCENDING          DESCENDING
Click C2:     ASCENDING           UNSORTED

实际发生的事情:

Sort Order in: Column 1           Column 2
Start:        ASCENDING           ASCENDING
Click C1:     DESCENDING          ASCENDING
Click C1:      UNSORTED           ASCENDING
Click C2:      UNSORTED           ASCENDING
Click C1:     DESCENDING          ASCENDING
Click C2:     DESCENDING          UNSORTED

正如您所看到的那样,TableRowSorter获取了应用的最后一个排序顺序而不是单击的列的排序顺序,而只是将下一个排序顺序应用于单击的下一列。我如何能够单独处理每个列并更新列以使其按预期工作?

这是一个MCV。我为之前不包括一个而道歉。

import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.SortOrder;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class MVC extends JFrame {
    private static final long serialVersionUID = -8809862571237032846L;

    private MVC() {
        setTitle("MVC");

        createAndRunGUI();

        pack();
        setVisible(true);
        setLocationRelativeTo(null);
    }

    private void createAndRunGUI() {
        setLayout(new GridLayout(1, 1));

        String[] tableHeaders = {"Col 1", "Col 2"};
        String[][] tableData = {
                {"Hi", "Animals"},
                {"Bob", "Of"},
                {"Phil", "The"},
                {"Dog", "World"},
                {"Cat", "Include"},
                {"Pill", "Fish"},
                {"Dab", "Ants"},
                {"Bob", "Hippos"},
                {"Fill", "Humans"},
                {"Space", "TVs"},
                {"Up", "Is"},
                {"Now", "That"},
                {"Even", "Right"},
                {"More", "Person"},
                {"Data", "?"}
            };

        JTable table = new JTable(tableData, tableHeaders);
        table.setAutoCreateRowSorter(true);
        ADU_SortOrder<TableModel> tableSorter = new ADU_SortOrder<TableModel>(table.getModel());
        List<SortKey> keys = new ArrayList<SortKey>();
        //keys.add(new RowSorter.SortKey( 0, SortOrder.ASCENDING));
        //keys.add(new RowSorter.SortKey( 1, SortOrder.ASCENDING));
        tableSorter.setSortKeys(keys);
        table.setRowSorter(tableSorter);

        JScrollPane myScrollTable = new JScrollPane(table);
        myScrollTable.setPreferredSize(new Dimension(600, 600));

        JPanel cont = new JPanel();
        cont.add(myScrollTable);

        getContentPane().add(cont);
    }

    public static void main(String[] args) {
        new MVC();
    }

    private class ADU_SortOrder<M extends TableModel> extends TableRowSorter<M> {
        public ADU_SortOrder(M model) {
            setModel(model);
        }

        @Override
        public void toggleSortOrder(int column) {
            List<? extends SortKey> sortKeys = getSortKeys();
            if (sortKeys.size() > 0) {
                List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
                keys.set(0, new SortKey(column, setNextOrder(sortKeys.get(0).getSortOrder())));
                setSortKeys(keys);
                return;
            }
            super.toggleSortOrder(column);
        }

        private SortOrder setNextOrder(SortOrder order) {
            switch (order) {
                case ASCENDING:
                    return SortOrder.DESCENDING;
                case DESCENDING:
                    return SortOrder.UNSORTED;
                case UNSORTED:
                    return SortOrder.ASCENDING;
                default:
                    return SortOrder.UNSORTED;
            }
        }
    }
}

编辑2
在程序运行时查看特定方法toggleSortOrder,很明显问题出在代码部分setNextOrder(keys.get(0).getSortOrder())上。这是因为当代码返回getSortKeys()作为ArrayList时,列表的大小只有01。这意味着当列表的长度为1时,代码get(0)会返回已排序的最后一列,但代码get(column)会导致IndexOutOfBoundsException。那么如何让程序获得每列的SortKeys

@Override
public void toggleSortOrder(int column) {
    System.out.println("Column: " + column);
    List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
    System.out.println("List Size: " + keys.size());
    if (keys.size() > 0) {
        keys.set(0, new SortKey(column, setNextOrder(keys.get(0).getSortOrder())));
        setSortKeys(keys);
        return;
    }
    super.toggleSortOrder(column);
}

编辑3

使用Andreas'建议我创建了一种能够使用keys.set(column, new SortKey(column, setNextOrder(keys.get(column).getSortOrder())));

的方法
List<SortKey> keys = new ArrayList<SortKey>();

@Override
public void toggleSortOrder(int column) {
    System.out.println("Column: " + column);
    System.out.println("List Size: " + keys.size());
    if (keys.size() > 0) {
        keys.set(column, new SortKey(column, setNextOrder(keys.get(column).getSortOrder())));
        setSortKeys(keys);
        return;
    }
    super.toggleSortOrder(column);
}

private SortOrder setNextOrder(SortOrder order) {
    switch (order) {
        case ASCENDING:
            return SortOrder.DESCENDING;
        case DESCENDING:
            return SortOrder.UNSORTED;
        case UNSORTED:
            return SortOrder.ASCENDING;
        default:
            return SortOrder.UNSORTED;
    }
}

private void initialSortOrder(M model) {
    for(int i = 0; i < model.getColumnCount(); i++) {
        keys.add(new RowSorter.SortKey( i, SortOrder.ASCENDING));
    }
}

但是,使用此方法可以对第1列进行排序,但只能在第二列中对单词OfHippo进行排序。我知道这已成为一个很长的问题而且很抱歉,但我非常感谢任何帮助

1 个答案:

答案 0 :(得分:0)

为了解决这个问题,我需要添加一些if语句和一个或两个变量。

import java.util.ArrayList;
import java.util.List;

import javax.swing.SortOrder;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class ADU_SortOrder<M extends TableModel> extends TableRowSorter<M> {
    public ADU_SortOrder(M model) {
        setModel(model);
    }

    boolean firstTime = true; //Needed in case there are any initial sort keys
    int columnHolder = -1;

    @Override
    public void toggleSortOrder(int column) {
        List<? extends SortKey> sortKeys = getSortKeys();
        if(sortKeys.size() == 0) { //For if there are no initial sort keys
            List<SortKey> keys = new ArrayList<SortKey>();
            keys.add(new SortKey(column, SortOrder.ASCENDING));
            setSortKeys(keys);
            return;
        }

        if (sortKeys.size() > 0 && columnHolder == column || firstTime) {
            if(firstTime) {
                firstTime = false;
                columnHolder = column;
                if(column != sortKeys.get(0).getColumn()) {
                    List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
                    keys.set(0, new SortKey(column, SortOrder.ASCENDING));
                    setSortKeys(keys);
                    return;
                }
            }

            List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
            keys.set(0, new SortKey(column, setNextOrder(sortKeys.get(0).getSortOrder())));
            setSortKeys(keys);
            return;
        } else if(sortKeys.size() > 0 && columnHolder != column && !firstTime) {
            List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
            keys.set(0, new SortKey(column, SortOrder.ASCENDING));
            setSortKeys(keys);
            columnHolder = column;
            return;
        }
        super.toggleSortOrder(column);
    }

    private SortOrder setNextOrder(SortOrder order) {
        switch (order) {
            case ASCENDING:
                return SortOrder.DESCENDING;
            case DESCENDING:
                return SortOrder.UNSORTED;
            case UNSORTED:
                return SortOrder.ASCENDING;
            default:
                return SortOrder.UNSORTED;
        }
    }
}