如何使用 JTable 的行排序器恢复原始行顺序?

发布于 2024-10-28 13:36:15 字数 111 浏览 2 评论 0原文

我已使用 setAutoCreateRowSorter 方法在 JTable 中启用排序。鼠标单击列标题将在升序和降序之间切换,但我想在升序、降序和原始(未排序)行顺序之间切换。有任何提示如何实现这一目标吗?

I've enabled sorting in JTable with setAutoCreateRowSorter method. Mouse clicks on the column headers will switch between ascending and descending order, but I would like to switch it between ascending, descending and the original (unsorted) row order. Any hints how to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

墨小沫ゞ 2024-11-04 13:36:15

鼠标单击到更改排序状态的映射是在 BasicTableHeaderUI 中实现的,并且仅通过 RowSorter 的toggleSortOrder(columnIndex) 发生。它的默认行为是切换

UNSORTED -->升序 -->降序 -->升序——

也就是说,无法回到未排序状态。如果要求只是简单地将圈子扩大为:

UNSORTED -->升序 -->降序 -- 未排序 --> ASCENDING ——

方法是子类化 TableRowSorter 并相应地重写其toggleSortOrder

    /** 
     * @inherited <p>
     */
    @Override
    public void toggleSortOrder(int column) {
        List<? extends SortKey> sortKeys = getSortKeys();
        if (sortKeys.size() > 0) {
            if (sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING) {
                setSortKeys(null);
                return;
            }
        }
        super.toggleSortOrder(column);
    }

注意:这有点简化,因为它不考虑 n 元排序列,请参阅 SwingX DefaultSortController 了解完整版本。或者使用SwingX开始,它的JXTable有api来配置排序周期,就像

 table.setSortOrderCycle(ASCENDING, DESCENDING, UNSORTED);

Cheers 一样
珍妮特

The mapping of a mouse click to changing the sort state is implemented in BasicTableHeaderUI and happens exclusively via the RowSorter's toggleSortOrder(columnIndex). It's default behaviour is to switch

UNSORTED --> ASCENDING --> DESCENDING --> ASCENDING --

that is, no way back into the UNSORTED. If the requirement is to simply widen the circle into:

UNSORTED --> ASCENDING --> DESCENDING -- UNSORTED --> ASCENDING --

the way to go is to subclass TableRowSorter and override its toggleSortOrder accordingly

    /** 
     * @inherited <p>
     */
    @Override
    public void toggleSortOrder(int column) {
        List<? extends SortKey> sortKeys = getSortKeys();
        if (sortKeys.size() > 0) {
            if (sortKeys.get(0).getSortOrder() == SortOrder.DESCENDING) {
                setSortKeys(null);
                return;
            }
        }
        super.toggleSortOrder(column);
    }

Note: this is a bit simplified as it doesn't account for n-ary sorted columns, see SwingX DefaultSortController for a full version. Or use SwingX to start with, its JXTable has api to configure the sorting cycle like

 table.setSortOrderCycle(ASCENDING, DESCENDING, UNSORTED);

Cheers
Jeanette

救星 2024-11-04 13:36:15

此代码实现循环 ASCENDING->DESCENDING->UNSORTED->... 而不重写 TableRowSorter:

TableRowSorter sorter = new TableRowSorter(getModel());
setRowSorter(sorter);
// Remove default sort MouseListener
for (MouseListener mouseListener : getTableHeader().getMouseListeners()) {
    if (mouseListener instanceof javax.swing.plaf.basic.BasicTableHeaderUI.MouseInputHandler) {
        getTableHeader().removeMouseListener(mouseListener);
    }
}
// Add MouseListener for onClick event
getTableHeader().addMouseListener(new MouseAdapter() {
    private SortOrder currentOrder = SortOrder.UNSORTED;

    @Override
    public void mouseClicked(MouseEvent e) {
        int column = getTableHeader().columnAtPoint(e.getPoint());
        RowSorter sorter = getRowSorter();
        List sortKeys = new ArrayList();
        switch (currentOrder) {
            case UNSORTED:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.ASCENDING));
                break;
            case ASCENDING:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.DESCENDING));
                break;
            case DESCENDING:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.UNSORTED));
                break;
        }
        sorter.setSortKeys(sortKeys);
    }
});

This code implements cycle ASCENDING->DESCENDING->UNSORTED->... without overriding TableRowSorter:

TableRowSorter sorter = new TableRowSorter(getModel());
setRowSorter(sorter);
// Remove default sort MouseListener
for (MouseListener mouseListener : getTableHeader().getMouseListeners()) {
    if (mouseListener instanceof javax.swing.plaf.basic.BasicTableHeaderUI.MouseInputHandler) {
        getTableHeader().removeMouseListener(mouseListener);
    }
}
// Add MouseListener for onClick event
getTableHeader().addMouseListener(new MouseAdapter() {
    private SortOrder currentOrder = SortOrder.UNSORTED;

    @Override
    public void mouseClicked(MouseEvent e) {
        int column = getTableHeader().columnAtPoint(e.getPoint());
        RowSorter sorter = getRowSorter();
        List sortKeys = new ArrayList();
        switch (currentOrder) {
            case UNSORTED:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.ASCENDING));
                break;
            case ASCENDING:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.DESCENDING));
                break;
            case DESCENDING:
                sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.UNSORTED));
                break;
        }
        sorter.setSortKeys(sortKeys);
    }
});
梦萦几度 2024-11-04 13:36:15

如果您使用的是 DefaultRowSorter:“空的 sortKeys 列表表示视图应该是未排序的,与模型相同。”

RowSorter rs = table.getRowSorter();
rs.setSortKeys(null);

附录:请注意 setSortKeys()

If you're using the DefaultRowSorter: "An empty sortKeys list indicates that the view should [be] unsorted, the same as the model."

RowSorter rs = table.getRowSorter();
rs.setSortKeys(null);

Addendum: Note that "null is a shorthand for specifying an empty list" in setSortKeys().

残龙傲雪 2024-11-04 13:36:15

科内尔的答案对我来说非常有用(谢谢!)

我做了这些更改,其他人可能会觉得有用:

  1. 将列从视图转换为模型坐标。这是原版的一个bug。
  2. 忽略删除其他鼠标侦听器,因为这样做会禁用列拖动和调整大小。
  3. 过滤除左键单击以外的任何内容
  4. 每当列更改时,重新初始化排序顺序。这种方式的用户体验明显更加直观,因为您可以连续单击不同的列并每次都获得升序。

    TableRowSorter 排序器 = new TableRowSorter(getModel());
    setRowSorter(排序器);
    getTableHeader().addMouseListener(new MouseAdapter() {
        私有 SortOrder currentOrder = SortOrder.UNSORTED;
        私有 int 最后列 = -1;
    
        @覆盖
        公共无效鼠标点击(MouseEvent e){
            int 列 = getTableHeader().columnAtPoint(e.getPoint());
            列=convertColumnIndexToModel(列);
            如果(列!=最后一列){
                当前顺序 = SortOrder.UNSORTED;
                最后列 = 列;
            }
            行排序器排序器 = getRowSorter();
            列表<排序键> sortKeys = new ArrayList();
            if (e.getButton() == MouseEvent.BUTTON1) {
                开关(当前订单){
                    案例未排序:
                        sortKeys.add(new RowSorter.SortKey(列, currentOrder = SortOrder.ASCENDING));
                    休息;
                    案例升序:
                        sortKeys.add(new RowSorter.SortKey(列, currentOrder = SortOrder.DESCENDING));
                    休息;
                    案例降序:
                        sortKeys.add(new RowSorter.SortKey(列, currentOrder = SortOrder.UNSORTED));
                    休息;
                }
                排序器.setSortKeys(sortKeys);
            }
        }
    });
    

Kornell's answer is working great for me (thanks!)

I made these changes which others may find helpful:

  1. Convert column from view to model coordinates. This is a bug in the original.
  2. Omit removing the other mouse listeners, because doing this disables column dragging and resizing.
  3. Filter out anything but left clicks
  4. Whenever column changes, reinitialize sort order. User experience is significantly more intuitive this way, as you can successively click different columns and get ascending order each time.

    TableRowSorter sorter = new TableRowSorter(getModel());
    setRowSorter(sorter);
    getTableHeader().addMouseListener(new MouseAdapter() {
        private SortOrder   currentOrder    = SortOrder.UNSORTED;
        private int         lastCol         = -1;
    
        @Override
        public void mouseClicked(MouseEvent e) {
            int column = getTableHeader().columnAtPoint(e.getPoint());
            column = convertColumnIndexToModel(column);
            if (column != lastCol) {
                currentOrder = SortOrder.UNSORTED;
                lastCol = column;
            }
            RowSorter<?> sorter = getRowSorter();
            List<SortKey> sortKeys = new ArrayList<SortKey>();
            if (e.getButton() == MouseEvent.BUTTON1) {
                switch (currentOrder) {
                    case UNSORTED:
                        sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.ASCENDING));
                    break;
                    case ASCENDING:
                        sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.DESCENDING));
                    break;
                    case DESCENDING:
                        sortKeys.add(new RowSorter.SortKey(column, currentOrder = SortOrder.UNSORTED));
                    break;
                }
                sorter.setSortKeys(sortKeys);
            }
        }
    });
    
薄荷港 2024-11-04 13:36:15

由于内置排序机制仅提供升序或降序,因此如果您在 JTable 附近的某个位置提供外部重新加载 JButton,则可以返回到原始状态,该按钮将相同的模型设置回您所显示的模型在进行任何排序活动之前,第一次查看该表。

Since the built-in sorting mechanism gives you ascending or descending order only, you could return to the original state if you provide an external reload-JButton, somewhere near your JTable, that just sets the same model back to what you had as you displayed the Table the first time, before any sorting activity took place.

没企图 2024-11-04 13:36:15

如果您正在寻找执行此操作的 UI 方式 - 按住 Shift 键并单击列标题即可执行此操作。这是内置的 JTable 功能

If you looking for UI way of doing it - shift-click on column header will do it. This is built-in JTable functionality

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文