When does a Java Swing JScrollBar update its size?

Viewed 56

I have a JTextArea in a JScrollPane, to which I append messages with display.append(). I am trying to make it scroll automatically by setting the value of the scroll bar to the maximum after appending the text. However, the value of getVerticalScrollBar().getMaximum()doesn't get updated immediately after a line is appended. I have tried to force an update with revalidate(), repaint() and updateUI(), but seem unable to find the right function.

MWE:

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class MessageDisplayPane extends JScrollPane {
    private static final long serialVersionUID = 2025745714938834689L;

    public static final int NUM_LINES = 5;

    private JTextArea display;
    private JScrollBar vertical = getVerticalScrollBar();

    public MessageDisplayPane() {
        display = createTextArea();
        setViewportView(display);
    }

    private JTextArea createTextArea() {
        JTextArea ta = new JTextArea(NUM_LINES, 0);
        ta.setEditable(false);
        ta.setLineWrap(true);
        ta.setWrapStyleWord(true);
        ta.setFont(new Font("Arial", Font.PLAIN, 12));
        ta.setBorder(BorderFactory.createEtchedBorder());
        return ta;
    }

    class EventListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            new Thread() {
                @Override
                public void run() {
                    System.out.println(vertical.getMaximum());

                    display.append("test\r\n");
                    revalidate();
                    repaint();
                    updateUI();

                    System.out.println(vertical.getMaximum());
                    System.out.println();

                    //vertical.setValue(vertical.getMaximum());
                }
            }.start();
            }
        }

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                MessageDisplayPane messagePane = new MessageDisplayPane();
                JButton button = new JButton("Display another line");

                frame.setSize(800, 300);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.getContentPane().add(button, BorderLayout.CENTER);
                frame.getContentPane().add(messagePane, BorderLayout.SOUTH);

                button.addActionListener(messagePane.new EventListener());

                frame.setVisible(true);
            }
        });
    }

}
1 Answers
Related