如何按字母顺序对JTable进行排序? [见图片澄清]

时间:2016-06-17 20:37:46

标签: java swing sorting jtable

如何按字母顺序对JTable进行排序,分隔线显示下一个字母的出现?例如,考虑Windows Media Player 12如何对其进行排序,

Windows Media Player 12, example

此问题的另一个例子是例如Macintosh'Finder'按日期排序最近打开应用程序的方式。我无法弄清楚他们是如何添加额外的行显示日期和包围匹配的行。

有关如何解决此问题的任何想法?

Macintosh, Finder, example

2 个答案:

答案 0 :(得分:1)

我会按字母顺序对数据进行分组,然后为我的数据中包含的每个字母创建一个单独的表格。

您可以使用TableCellRenderer自定义标题的显示以获得所需的外观,如果您要添加更多列,如示例所示,您可以将标题替换为另一个组件。

public class MyTableFrame extends JFrame {

    MyTableFrame() {

        List<String> data = Arrays.asList(
            "Alpha1",
            "Beta1",
            "Alpha2",
            "Charlie2",
            "Alpha3",
            "Beta2",
            "Charlie1"
        );
        // Sort alphabetically
        data.sort(String::compareTo);

        // Group by first letter
        Map<Character, List<String>> collect = data.stream()
                .collect(Collectors.groupingBy(string -> string.charAt(0)));

        JPanel tablesContainer = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 0;
        c.gridy = 0;

        // Create a table for each Letter
        collect.entrySet().forEach(mapEntry -> {
            Character letter = mapEntry.getKey();
            List<String> startingWithLetter = mapEntry.getValue();
            TableModel tableModel = new TableModel(startingWithLetter, letter);
            JTable table = new JTable(tableModel);
            // Table header must be added separately since there is no scroll pane
            JTableHeader tableHeader = table.getTableHeader();
            tablesContainer.add(tableHeader, c);

            c.gridy++;
            tablesContainer.add(table, c);

            c.gridy++;
        });

        add(tablesContainer);
        setVisible(true);
        pack();
    }

    static class TableModel extends AbstractTableModel {
        private List<String> data;
        private Character columnName;

        TableModel(List<String> data, Character columnName) {
            this.data = data;
            this.columnName = columnName;
        }

        @Override
        public String getColumnName(int column) {
            return columnName.toString();
        }

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

        @Override
        public int getColumnCount() {
            return 1;
        }

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

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

答案 1 :(得分:1)

要使表行显示在JTable通常期望的位置以外的位置,您需要覆盖的JTable中的方法是fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;rowAtPoint,当然,{ {1}}。为了支持这些方法,我会跟踪排序地图中部分标题出现的行,并且我会跟踪第二个有序地图中的行位置。

每当表模型或排序列发生更改时,或者每当表因任何原因验证自身时,我都会重新计算这些映射,这意味着分别覆盖tableChanged,sortedChanged和validate方法。

结果并不像您预期​​的那样冗长:

getCellRect

您可以通过更改标题从数据中派生的方式来调整此类以生成Finder表。仅使用getValueAt检查一个单元格是不够的;相反,您需要translate the sorted row to the corresponding model row,并直接从TableModel获取该行的数据对象。然后,您可以按年龄而不是字符串数据比较行。