How to scroll to last row in a JTable

前端 未结 4 1194
梦谈多话
梦谈多话 2020-12-14 22:34

I am trying to use JTable in the way where new data record are added to the end. The strange thing is the scroll bar does not go to the end of the table; instea

4条回答
  •  时光取名叫无心
    2020-12-14 23:17

    I just ran into this problem - there is actually nothing wrong with that line of code; the problem lies in when you execute it.

    If you're, like me, trying to execute it immediately after manipulating the TableModel (even via invokeLater) or by using a TableModelListener, you'll get the problem you're describing. The problem is that while the model has been updated with the new data (table.getRowCount() is simply a pass-through to the getRowCount() method on your TableModel), the JTable component visually has not.

    When you execute that line of code in the previously described places, you're actually trying to tell the JScrollPane (JTable.scrollRectToVisible defers any action to a parent that can provide scrolling behaviour, e.g. JScrollPane) to scroll beyond the end of the enclosed JTable component. It refuses to do that, and instead scrolls to the current end of the JTable component instead.

    At some point later, the JTable component updates itself visually, and adds the newly added row underneath the row scrolled to earlier. You can verify that that line of code works by adding a button that executes it independently of the code that adds new rows, e.g.

    private JTable _table = new JTable();
    ...
    JButton b = new JButton("Force scroll to bottom");
    b.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) { 
            _table.scrollRectToVisible(_table.getCellRect(_table.getRowCount()-1, 0, true));
        }
    });
    this.add(b);
    

    The solution to this problem is a little indirect, but does work reliably in my testing. Because the issue lies in the visual side of things, I decided to hook into the ComponentListener instead, which provides, among other things, a componentResized method. Whenever a row is added or removed, the JTable resizes, even if it cannot be seen visually due to the JScrollPane's viewport. Therefore just run that line of code in that listener method, and things will work as expected.

    private JTable _table = new JTable();
    ...
    _table.addComponentListener(new ComponentAdapter() {
        public void componentResized(ComponentEvent e) {
            _table.scrollRectToVisible(_table.getCellRect(_table.getRowCount()-1, 0, true));
        }
    });
    

提交回复
热议问题