java - 自定义 TableHeaderUI 破坏了自定义 TableRowSorter

标签 java swing sorting jtable jtableheader

我编写了一个自定义 TableRowSorter,当您单击
SortOrder.UNSORTED => 中的 JTableHeader 时,它会更改排序顺序SortOrder.ASCENDING => SortOrder.DESCENDING => SortOrder.ASCENDING => SortOrder.DESCENDING => .. .
to
SortOrder.UNSORTED => SortOrder.ASCENDING => SortOrder.DESCENDING =>SortOrder .UNSORTED => SortOrder.ASCENDING => SortOrder.DESCENDING => ...

ADU_SortOrder.java

package order;

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;
        }
    }
}

当你实现这样的东西时,它的效果非常好

JTableTest.java - 工作示例

import java.awt.GridLayout;

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

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

import order.ADU_SortOrder;

@SuppressWarnings("serial")
public class JTableTest extends JFrame {
    private JTableTest() {
        super("JTable Test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        pack();
        setVisible(true);
    }

    JPanel panel = new JPanel(new GridLayout(1, 1));
    JScrollPane scroll;

    private void createPanel() {
        Object[] headers = {"Select", "Title", "Artist", "Length", "Title"};
        Object[][] sampleData = {{true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"},
                {false, "Spanish Train", "Chris De Burgh", "358", "Spanish Train"},
                {true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"}};
        JTable table = new JTable(sampleData, headers);

        //Sort Order Part
        ADU_SortOrder<TableModel> sortOrder = new ADU_SortOrder<TableModel>(table.getModel());
        List<RowSorter.SortKey> sortKeys = new ArrayList<>();
        sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
        sortOrder.setSortKeys(sortKeys);
        table.setRowSorter(sortOrder);

        scroll = new JScrollPane(table);
        panel.add(scroll);
        getContentPane().add(panel);
    }

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

但是,一旦添加自定义 BasicTableHeaderUI(例如下面的示例)。

CustomHeaderUI.java

package ui;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.TableColumnModel;

@SuppressWarnings("serial")
public class CustomHeaderUI extends BasicTableHeaderUI {
    public void canReorder(String col, boolean reorder) {
        TableColumnModel cM = header.getColumnModel();

        for(int i = 0; i < cM.getColumnCount(); i++) {
            if(header.getTable().getColumnName(i).equals(col)) {
                canReorder(i, reorder);
                break;
            }
        }
    }

    public void canReorder(String col, int instance, boolean reorder) {
        TableColumnModel cM = header.getColumnModel();
        int column = -1;

        for(int i = 0; i < cM.getColumnCount(); i++) {
            if(header.getTable().getColumnName(i).equals(col)) {
                column++;
                if(column == instance - 1) {
                    canReorder(i, reorder);
                    break;
                }
            }
        }
    }

    public void canReorderAll(String col, boolean reorder) {
        TableColumnModel cM = header.getColumnModel();

        for(int i = 0; i < cM.getColumnCount(); i++) {
            if(header.getTable().getColumnName(i).equals(col))
                canReorder(i, reorder);
        }
    }

    public void canReorder(int col, boolean reorder) {

    }
}

JTableTest.java - SSSCE/MCVE

import java.awt.GridLayout;

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

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

import order.ADU_SortOrder;

import ui.CustomHeaderUI;

@SuppressWarnings("serial")
public class JTableTest extends JFrame {
    private JTableTest() {
        super("JTable Test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        pack();
        setVisible(true);
    }

    JPanel panel = new JPanel(new GridLayout(1, 1));
    JScrollPane scroll;

    private void createPanel() {
        Object[] headers = {"Select", "Title", "Artist", "Length", "Title"};
        Object[][] sampleData = {{true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"},
                {false, "Spanish Train", "Chris De Burgh", "358", "Spanish Train"},
                {true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"}};
        JTable table = new JTable(sampleData, headers);
        ADU_SortOrder<TableModel> sortOrder = new ADU_SortOrder<TableModel>(table.getModel());
        List<SortKey> keys = new ArrayList<SortKey>();
        keys.add(new RowSorter.SortKey( 0, SortOrder.ASCENDING));
        sortOrder.setSortKeys(keys);
        table.setRowSorter(sortOrder);

        //Adds Custom UI
        CustomHeaderUI headerUI = new CustomHeaderUI();
        headerUI.installUI(table.getTableHeader());

        headerUI.canReorder("Title", true);
        headerUI.canReorder("Title", 1, true);
        headerUI.canReorderAll("Title", true);
        headerUI.canReorder(3, true);

        scroll = new JScrollPane(table);
        panel.add(scroll);
        getContentPane().add(panel);
    }

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

其中包括一些示例 CustomHeaderUI 方法,清楚地显示了这两个问题。首先,排序顺序不正确。如果从第一列(第 0 列)开始,排序顺序为
SortOrder.ASCENDING => SortOrder.UNSORTED => SortOrder.DESCENDING => SortOrder.ASCENDING => SortOrder.UNSORTED => SortOrder.DESCENDING => ...

由于 keys.add(new RowSorter.SortKey( 0, SortOrder.ASCENDING)); 开始升序,而不是因为我的代码出现故障

这不是开头描述的所需排序顺序。第二个问题是,当您拖动 MCVE 中的列时,它会跳过两列而不是一列。我非常感谢帮助解决这些问题。

最佳答案

headerUI.installUI(table.getTableHeader());

在本例中,MouseListener 被重复安装在 JTableHeader 中。

javax.swing.ToolTipManager@726e5bdf
javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler@600da835
TEST: installUI
javax.swing.ToolTipManager@726e5bdf
javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler@600da835
javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler@17f30210
import java.awt.*;
import java.awt.event.*;
// import java.util.List;
// import java.util.ArrayList;
import javax.swing.*;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.*;
import javax.swing.table.TableColumnModel;
//import ui.CustomHeaderUI;

public class JTableTest2 extends JFrame {
  private JTableTest2() {
    super("JTable Test");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new GridLayout(1, 1));
    createPanel();
    pack();
    setVisible(true);
  }

  JPanel panel = new JPanel(new GridLayout(1, 1));

  private void createPanel() {
    Object[] headers = {"Select", "Title", "Artist", "Length", "Title"};
    Object[][] sampleData = {
      {true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"},
      {false, "Spanish Train", "Chris De Burgh", "358", "Spanish Train"},
      {true, "Bat Outta Hell", "Meat Loaf", "673", "Bat Outta Hell"}
    };
    JTable table = new JTable(sampleData, headers);

    // Custom TableRowSorter is completely irrelevant to this problem:
    // //Sort Order Part
    // ADU_SortOrder<TableModel> sortOrder = new ADU_SortOrder<>(table.getModel());
    // List<RowSorter.SortKey> sortKeys = new ArrayList<>();
    // sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
    // sortOrder.setSortKeys(sortKeys);
    // table.setRowSorter(sortOrder);

    JTableHeader header = table.getTableHeader();
    testPrintMouseListener(header);

    //Adds Custom UI
    CustomHeaderUI headerUI = new CustomHeaderUI();
    //XXX: headerUI.installUI(table.getTableHeader());
    table.getTableHeader().setUI(headerUI);

    testPrintMouseListener(header);

    panel.add(new JScrollPane(table));
    getContentPane().add(panel);
  }

  private static void testPrintMouseListener(JTableHeader header) {
    for (MouseListener l : header.getMouseListeners()) {
      System.out.println(l);
    }
  }

  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      new JTableTest2();
    });
  }
}

class CustomHeaderUI extends BasicTableHeaderUI {
  @Override public void installUI(JComponent c) {
    super.installUI(c);
    System.out.println("TEST: installUI");
  }
}

关于java - 自定义 TableHeaderUI 破坏了自定义 TableRowSorter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40795016/

相关文章:

python - 如何按值(DESC)然后按键(ASC)对字典进行排序?

java - 在Java中查找一个月中的天数

java - 数组中的长度字段

java - 正则表达式捕获未知数量的重复组

java - 创建条目列表并使每个条目都可点击

Java 计算器显示不正确的结果

java - 在java中,只有鼠标悬停在按钮上才会显示按钮

algorithm - 公平地对新项目进行排名?

java - Thread Local - 我做错了什么?

javascript - 在对数组中找到最接近的数字对的最快方法是什么