使用JTable和JScroll Panes滚动锁定

时间:2011-09-12 22:18:16

标签: java swing locking jtable jscrollpane

我有一个JTable,它是使用EventTableModel创建的,位于JScrollPane中。 EventTableModel从eventList获取实时更新,并在表中显示结果。随着新结果进入表格,新信息显示在表格的顶部。

然而,我想要做的是冻结表格以显示当我按下名为“锁定表格”的按钮时当前显示的内容。此按钮应与eclipse控制台的“Scroll Lock”具有相同的效果,因此当新项目出现时,当前项目应保留在屏幕上,并且在新项目出现时不会被推下。但是仍然应该添加新项目,而不是自动滚动到。

有谁知道如何尝试实现此功能。因此,当更新进入时,表格上的数据不会被强制关闭屏幕,因此当按下复选框时,焦点将保留在当前数据上。

感谢您的帮助。 迈克尔

1 个答案:

答案 0 :(得分:2)

基本程序(用于插入当前显示区域之上)

  • 在表的模型上安装TableModelListener
  • 启用锁定:记下当前可见矩形下方的行数
  • 在锁定时接收插入,滚动以使下面的行数保持不变

一些工作代码(使用JXTable,因为它有方便的滚动方法,核心表只需自己进行计算: - )

public static class ScrollLock {
    private JXTable table;
    private boolean blocked;
    private int rowsBelow;

    public ScrollLock(JXTable table) {
        this.table = table;
        table.getModel().addTableModelListener(getTableModelListener());
    }

    private TableModelListener getTableModelListener() {
        TableModelListener l = new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                if (!blocked) return;
                if (e.getType() == TableModelEvent.INSERT) {
                    updateInsert(e.getFirstRow(), e.getLastRow());
                }
            }

        };
        return l;
    }

    protected void updateInsert(int firstRow, int lastRow) {
        // PENDING: assumption is that insert always above
        // need additional logic for other cases
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Rectangle r = table.getVisibleRect();
                int row =table.rowAtPoint(new Point(0, r.y + r.height));
                int lastVisible = table.getRowCount() - rowsBelow;
                table.scrollRowToVisible(lastVisible);
            }
        });
    }

    public void block() {
        Rectangle viewRect = table.getVisibleRect();
        int lastVisibleRow = table.rowAtPoint(new Point(0, viewRect.y + viewRect.height));
        rowsBelow = table.getRowCount() - lastVisibleRow;
        blocked = true;
    }

    public void unblock() {
        blocked = false;
        rowsBelow = -1;
    }

}