0

AutoCreateRowSorterプロパティがtrueに設定されたJTableがあります。クリックすると問題なく動作しますが、クリック中に1pxだけマウスを動かすと、並べ替えが表示されないため、状況によっては不快になります。これを修正する方法は?

UPDマウスを離したときにソートを表示したいだけです。

4

1 に答える 1

1

汚い(読んでください:あなたが絶対に必死でなく、あなたが何をしているのかを正確に知っているのでなければいけません!)アプローチは、uiDelegateによってインストールされたMouseListenerにフックし、sortトリガーをリリースされたメソッドに移動することです。これには

  • クリックされたものを除くすべてのイベントを最初にインストールされたものに委任し、リリースされたものを渡す前にソートするカスタムMouseListener
  • オリジナルをカスタムに置き換えます
  • LAFが変更されるたびに置換を更新します(元のファイルはUIによって制御されるため)。これには、JTableHeaderのサブクラス化が必要であり、updateUIで配線を行います。

カスタムリスナー:

public static class EventHook implements MouseListener {

    private JTableHeader header;
    private MouseListener delegate;

    public EventHook(JTableHeader header) {
        this.header = header;
        installHook();
    }

    protected void installHook() {
        MouseListener[] listeners = header.getMouseListeners();
        for (int i = 0; i < listeners.length; i++) {
            MouseListener l = listeners[i];
            if (l.getClass().getName().contains("TableHeaderUI")) {
                this.delegate = l;
                listeners[i] = this;
            }
            header.removeMouseListener(l);
        }
        for (MouseListener l : listeners) {
            header.addMouseListener(l);
        }
    }

    public void uninstallHook() {
        MouseListener[] listeners = header.getMouseListeners();
        for (int i = 0; i < listeners.length; i++) {
            MouseListener l = listeners[i];
            if (l == this) {
                listeners[i] = delegate;
            }
            header.removeMouseListener(l);
        }
        for (MouseListener l : listeners) {
            header.addMouseListener(l);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // sort before calling super
        sort(e);
        delegate.mouseReleased(e);
    }

    private void sort(MouseEvent e) {
        if (!header.isEnabled()) {
            return;
        }
        // do nothing if dragged
        if (header.getDraggedDistance() != 0) {
            return;
        }
        if (e.getClickCount() % 2 == 1 &&
                SwingUtilities.isLeftMouseButton(e)) {
            JTable table = header.getTable();
            RowSorter sorter;
            if (table != null && (sorter = table.getRowSorter()) != null) {
                int columnIndex = header.columnAtPoint(e.getPoint());
                if (columnIndex != -1) {
                    columnIndex = table.convertColumnIndexToModel(
                            columnIndex);
                    sorter.toggleSortOrder(columnIndex);
                }
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // swallow the clicked - want to trigger sort on released
    }

    @Override
    public void mousePressed(MouseEvent e) {
        delegate.mousePressed(e);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        delegate.mouseEntered(e);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        delegate.mouseExited(e);
    }

}

サブクラス化されたJTableHeader

public static class MyTableHeader extends JTableHeader {
    private EventHook hook;
    public MyTableHeader(TableColumnModel model) {
        super(model);
    }
    @Override
    public void updateUI() {
        if (hook != null) {
            hook.uninstallHook();
            hook = null;
        }
        super.updateUI();
        hook = new EventHook(this);
    }

}

使用法は、JTableをサブクラス化し、createDefaultTableHeaderをオーバーライドするか、ヘッダーを手動で設定します。

// either subclass
JTable table = new JTable(new AncientSwingTeam()) {

    @Override
    protected JTableHeader createDefaultTableHeader() {
        return new MyTableHeader(getColumnModel());
    }

};
table.setAutoCreateRowSorter(true);
于 2013-01-21T13:22:29.227 に答える