I need to scroll a JScrollPane to the bottom. The JScrollPane contains a JPanel, which contains a number of JLabel\'s.
To scroll to the top, I just do:
I wanted to contribute my findings to this question, since I needed an answer for it today, and none of the solutions here worked for me, but I did finally find one that did. I had a JList object wrapped in a JScrollPane which I wanted to scroll to the last item after all elements had been added to a DefaultListModel. It essentially works like this:
JList list = new JList();
DefaultListModel listModel = new DefaultListModel();
JScrollPane listScroller = new JScrollPane(list);
public void populateList()
{
//populate the JList with desired items...
list.ensureIndexIsVisible(listModel.indexOf(listModel.lastElement()));
}
I tried all of the solutions listed here but none seemed to have any effect. I found this one while experimenting, and it works perfectly. Thought I'd leave it here in the case it might help someone else.
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());
}
// Scroll to bottom of a JScrollPane containing a list of Strings.
JScrollPane scrollPane;
DefaultListModel listModel;
JList list;
listModel = new DefaultListModel();
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.VERTICAL);
list.setVisibleRowCount(-1); // -1 = display max items in space available
scrollPane = new JScrollPane(list);
scrollPane.setPreferredSize(new Dimension(200, 50));
// Append text entries onto the text scroll pane.
listModel.addElement("text entry one");
listModel.addElement("text entry two");
listModel.addElement("text entry three");
listModel.addElement("text entry four");
// Get the index of the last entry appended onto the list, then
// select it, and scroll to ensure it is visible in the vewiport.
int lastNdx = listModel.getSize() - 1;
list.setSelectedIndex(lastNdx);
list.ensureIndexIsVisible(lastNdx);
JPanel panel = new JPanel();
panel.add(scrollPane);
JScrollBar vertical = scrollPane.getVerticalScrollBar();
vertical.setValue( vertical.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.
If you look at the JTextArea documentation
public void select(int selectionStart, int selectionEnd)
Selects the text between the specified start and end positions. This method sets the start and end positions of the selected text, enforcing the restriction that the start position must be greater than or equal to zero. The end position must be greater than or equal to the start position, and less than or equal to the length of the text component's text.
If the caller supplies values that are inconsistent or out of bounds, the method enforces these constraints silently, and without failure. Specifically, if the start position or end position is greater than the length of the text, it is reset to equal the text length. If the start position is less than zero, it is reset to zero, and if the end position is less than the start position, it is reset to the start position.
So the simple solution is jTextArea.select(Integer.MAX_VALUE, 0); and let Java sort it out!