1

ログイベントをテーブルに表示するウィンドウがあります。たとえば、ユーザーがテーブルのある行のテキストを読んでいるとします。新しいログが来ると、テーブルの先頭に追加され、ユーザーが読んでいた行が下に移動します。テーブルの先頭に新しい行が追加されたときに JScrollPane がスクロールしないようにする必要があります。私はさまざまなことを試しましたが、何も役に立ちませんでした。誰かがこれを実装する方法を教えてもらえますか? 前もって感謝します!

4

1 に答える 1

1

トリッキーな作業 :-) デフォルトでは、スクロール位置がまったく調整されないため、移動が発生します。上に行を追加すると、垂直スクロール位置が保持され、以前と同じように別の行がポイントされます。

必要なもの:

  • 挿入の visibleRect/最後の行を追跡する
  • type insert のモデル変更をリッスンする
  • 古い最後の行がスクロールしてビューに戻るように、新しい可視四角形を計算します
  • スクロールをトリガーする

モデルの変更を聞く必要があるため、注意が必要です。そのリスナーは、変更時に自分自身を更新するテーブルによって内部的に登録された modelListener の隣人です。したがって、内部の変更が行われた後に確実に行動すると同時に、内部の更新前に情報を使用する必要があります。

汚い解決策 - スイングリスナー通知の通常のシーケンス (最後に追加された後、最初に通知される) に依存する (注意:プロダクションコードではいけません! LAF を変更すると簡単に壊れてしまいます) - 変更前の状態を収集することです。通知され、invokeLater でラップされたスクロール位置を調整します。

final DefaultTableModel model = new DefaultTableModel(20, 2);
for (int i = 0; i < model.getRowCount(); i++) {
    model.setValueAt(i, i, 0);
}
final JTable table = new JTable(model);
Action action = new AbstractAction("add row at 0") {

    @Override
    public void actionPerformed(ActionEvent e) {
        model.insertRow(0, new Object[] {});
    }
};
JXFrame frame = wrapWithScrollingInFrame(table, "modify scroll");
TableModelListener l = new TableModelListener() {

    @Override
    public void tableChanged(TableModelEvent e) {
        if (!TableUtilities.isInsert(e)) return;
        final Rectangle r = table.getVisibleRect();
        final int lastRow = table.rowAtPoint(
                new Point(0, r.y + r.height - 5));
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // assuming 
                // a) the insert was exactly 1 row
                // b) was _before_ the old last row in view-coordinates
                Rectangle cell = table.getCellRect(lastRow + 1, 0, true);
                cell.translate(0, -r.height + cell.height);
                cell.height = r.height;
                table.scrollRectToVisible(cell);
            }
        });
    }
};
model.addTableModelListener(l);

前の状態をきれいに取得する適切な方法は、正確なコンテキストによって異なります。テーブルの存続期間中に最初/最後の行を追跡し、それらを (1 つまたはすべて) 更新することができます。

  • 行 selectionModel への ListSelectionListener (ユーザーが読み取っている行が常に選択されている場合)
  • 垂直スクロールバーへの ChangeListener
  • scrollPane のサイズを変更するための ComponentListener
于 2013-08-24T16:56:19.690 に答える