Scroll JScrollPane to bottom

JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue( vertical.getMaximum() );

After many hours of attempting to find an answer other than one using the scrollRectToVisible() method, I've succeeded. I've found that if you use the following code after you output text to the text area in the scrollpane, it will automatically focus on the bottom of the text area.

textArea.setCaretPosition(textArea.getDocument().getLength());

So, at least for me, my print method looks like this

public void printMessage(String message)
{
    textArea.append(message + endL);
    textArea.setCaretPosition(textArea.getDocument().getLength());
}

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
        e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
    }
});

Instead of setViewPosition(), I usually use scrollRectToVisible(), described in How to Use Scroll Panes. You could use the result of an appropriate label's getBounds() for the required Rectangle.

Addendum: @Matt notes in another answer, "If you use the following code after you output text to the text area in the scrollpane, it will automatically focus on the bottom of the text area."

In the particular case of a JTextComponent, also consider using the setUpdatePolicy() method of DefaultCaret to ALWAYS_UPDATE, illustrated here.


I adapted the code of Peter Saitz. This version leaves the scrollbar working after it has finished scrolling down.

private void scrollToBottom(JScrollPane scrollPane) {
    JScrollBar verticalBar = scrollPane.getVerticalScrollBar();
    AdjustmentListener downScroller = new AdjustmentListener() {
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e) {
            Adjustable adjustable = e.getAdjustable();
            adjustable.setValue(adjustable.getMaximum());
            verticalBar.removeAdjustmentListener(this);
        }
    };
    verticalBar.addAdjustmentListener(downScroller);
}