【问题标题】:How to make JScrollPane not to scroll after adding rows in the beginning of table在表的开头添加行后如何使 JScrollPane 不滚动
【发布时间】:2013-08-20 08:16:26
【问题描述】:

我有一个在表格中显示日志事件的窗口。 例如,用户正在阅读表格某行中的文本。当新日志出现时,它们被添加到表的开头,并且用户正在阅读的行向下移动。当在表的开头添加新行时,我需要防止 JScrollPane 滚动。我尝试了不同的东西,但没有任何帮助。有人可以建议我如何实施吗? 提前致谢!

【问题讨论】:

    标签: java swing jtable focus jscrollpane


    【解决方案1】:

    棘手的任务 :-) 搬出是因为默认情况下滚动位置以任何方式调整:在上面添加行只是保持垂直滚动位置,然后像以前一样指向不同的行.

    需要什么:

    • 跟踪可见矩形/最后一行在插入之前
    • 监听插入类型的模型变化
    • 计算新的可见矩形,以便将旧的最后一行滚动回视图中
    • 触发滚动

    这很棘手,因为我们需要倾听模型的变化。该侦听器是由表在内部注册的 modelListener 的邻居,该表在更改时自行更新。所以我们需要确保内部更改完成后采取行动,同时使用内部更新之前的信息。

    一个肮脏的解决方案 - 取决于摆动侦听器通知的通常顺序,这是最后添加的第一个通知(注意:生产代码中的 DONT!它很容易中断,f.i. 在更改 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);
    

    干净地获取之前状态的适当方法取决于您的确切上下文。您可以在表的生命周期内跟踪第一行/最后一行,并在(一个或全部)中更新它们

    • 行 selectionModel 的 ListSelectionListener(如果用户正在阅读的行始终被选中)
    • 垂直滚动条的 ChangeListener
    • 一个 ComponentListener 来改变 scrollPane 的大小

    【讨论】:

    • 感谢您的回复!我帮忙了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多