Слушатель модели JTable обнаруживает вставленные строки слишком рано (до их отрисовки)

у меня естьJTable которые могут иметь строки, динамически добавляемые пользователем. Он сидит вJScrollPane, так как количество строк становится достаточно большим, скроллер становится активным. Мое желание состоит в том, чтобы, когда пользователь добавляет новую строку, скроллер перемещался полностью вниз, так что новая строка видна в области прокрутки. В настоящее время я (SSCCE ниже) пытаюсь использовать слушатель модели таблицы, чтобы определить, когда вставлена строка, и полностью переместить полосу прокрутки вниз, когда будет выполнено обнаружение. Тем не менее, кажется, что это обнаружение «слишком рано», так как модель обновилась, но новая строка на самом деле еще не нарисована, поэтому происходит то, что скроллер перемещается полностью до самого днадо новая строка вставляется, а затем новая строка вставляется чуть ниже конца панели (вне видимости).

Очевидно, что этот подход как-то не так. Какой правильный подход?

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class TableListenerTest {

    private JFrame frame;
    private JScrollPane scrollPane;
    private JTable table;
    private DefaultTableModel tableModel;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TableListenerTest window = new TableListenerTest();
                    window.frame.setVisible(true);
      ,          } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public TableListenerTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));

        JSplitPane splitPane = new JSplitPane();
        frame.getContentPane().add(splitPane);

        scrollPane = new JScrollPane();
        scrollPane.setPreferredSize(new Dimension(100, 2));
        splitPane.setLeftComponent(scrollPane);

        tableModel = new DefaultTableModel(new Object[]{"Stuff"},0);
        table = new JTable(tableModel);
        scrollPane.setViewportView(table);
        table.getModel().addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                if (e.getType() == TableModelEvent.INSERT) {
                    JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
                    scrollBar.setValue(scrollBar.getMaximum());
                }
            }
        });

        JButton btnAddRow = new JButton("Add Row");
        btnAddRow.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                tableModel.addRow(new Object[]{"new row"});
            }
        });
        splitPane.setRightComponent(btnAddRow);
    }
}

РЕДАКТИРОВАТЬ: Обновлен SSCCE ниже на основе запроса trashgod. Эта версия все еще не работает, однако, если я переместил логику прокрутки от слушателя модели таблицы к слушателю кнопки, как он сделал, то это работает!

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

    public class TableListenerTest {

        private JFrame frame;
        private JScrollPane scrollPane;
        private JTable table;
        private DefaultTableModel tableModel;

        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        TableListenerTest window = new TableListenerTest();
                        window.frame.setVisible(true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        public TableListenerTest() {
            initialize();
        }

        private void initialize() {
            frame = new JFrame();
            frame.setBounds(100, 100, 450, 200);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));

            JSplitPane splitPane = new JSplitPane();
            frame.getContentPane().add(splitPane);

            scrollPane = new JScrollPane();
            scrollPane.setPreferredSize(new Dimension(100, 2));
            splitPane.setLeftComponent(scrollPane);

            tableModel = new DefaultTableModel(new Object[]{"Stuff"},0);
            table = new JTable(tableModel);
            scrollPane.setViewportView(table);
            table.getModel().addTableModelListener(new TableModelListener() {
                public void tableChanged(TableModelEvent e) {
                    if (e.getType() == TableModelEvent.INSERT) {
                        int last = table.getModel().getRowCount() - 1;
                        Rectangle r = table.getCellRect(last, 0, true);
                        table.scrollRectToVisible(r);
                    }
                }
            });

            JButton btnAddRow = new JButton("Add Row");
            btnAddRow.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    tableModel.addRow(new Object[]{"new row"});
                }
            });
            splitPane.setRightComponent(btnAddRow);
        }
    }

Ответы на вопрос(2)

Ваш ответ на вопрос