I am trying to implement a JScrollPane, containing a JTextArea, whose vertical scroll bar automatically remains as the bottom when new text is added, if it is already at the bottom, and stays in place otherwise.
I have found a solution that seems to work, except when I move the scroll bar to the bottom, it gets stuck there and can only be moved by dragging the scroll bar, pressing the scroll bar's up arrow and the mouse wheel do not work when the scroll bar is at the bottom. Both methods, up arrow on scroll bar and mouse wheel, do work to more the scroll bar if it is not at the bottom.

Since this is a small part of a larger application, I am only including relevant code snippets. Please assume all variables have been properly initialized and let me know if you need more code

//Child class of JScrollPane
public class AutoScrollPane extends JScrollPane
{
  private boolean shouldScroll = false;
  public AutoScrollPane(JTextArea t)
  {
    super(t);
  }
  public void setShouldScroll (boolean b)
  {
    shouldScroll = b;
  }
  public boolean getShouldScroll ()
  {
    return shouldScroll;
  }
} //end class
//in main
JTextArea text = new JTextArea(10, 10);
AutoScrollPane scroller = new AutoScrollPane(text);
scroller.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener()
{ public void adjustmentValueChanged(AdjustmentEvent e) {onChangeScrollBarMethod(); }});

private void onChangeScrollBarMethod()
{
  if (!scroller.getVerticalScrollBar().getValueIsAdjusting() &&  scroller.getVerticalScrollBar().getValue() + scroller.getVerticalScrollBar().getVisibleAmount() == scroller.getVerticalScrollBar().getMaximum())
scroller.setShouldScroll(true);
  else
scroller.setShouldScroll(false);
}
private Thread guiThread = null;
//in main
execute(new Runnable() { public void run() { startGuiThread(); }});

private void startGuiThread()
{
  if (guiThread == null)
  {
    guiThread = new Thread(new Runnable() { public void run() { updateGui(); }});
    guiThread.setDaemon(true);
    guiThread.start();
  }
}

private void updateGui()
{
  while(true)
  {
    if (scroller.getShouldScroll())
    {
      try { EventQueue.invokeAndWait(new Runnable() { public void run() { scroller.getVerticalScrollBar().setValue(scroller.getVerticalScrollBar().getMaximum());}}; }
      catch (Exception e) { e.printStackTrace(); }
    }
//append text
}

Without a working example these are hard to debug unless someone has had the exact same problem.

Have you tried debugging the code by adding some println() statements to show where the code is executing etc?
With the threads and listeners, there could be something that is not foreseen.

Edited 6 Years Ago by NormR1: n/a

@NormR1 thanks for the insight. I have tried doing that and it looked like the Adjustment Listener has not being triggered at the right times.
I have since developed a different, and in my opinion easier, way to have a scroll bar that automatically scrolls down when text is appended if the scroll bar was at the bottom before the text was appended.
For anyone trying to figure this out, here is my solution:

public class AutoScrollTextArea extends JTextArea
{
  private JScrollPane scroller;
  private int rows;
  private int cols;

  public AutoScrollTextArea (int r, int c)
  {
     super(r,c);
     rows = r;
     cols = c;
     scroller = new JScrollPane(this);
  }
  
  public JScrollPane getScrollPane ()
  {
     return scroller;
  }
  
  public boolean isAtBottom()
  {
    Adjustable sb = this.scroller.getVerticalScrollBar();
    int lowest = sb.getValue() + sb.getVisibleAmount();
    return (lowest == sb.getMaximum());
  }

  public void scrollToBottom ()
  {
    try {
      final AutoScrollTextArea t = this;
      SwingUtilities.invokeAndWait(new Runnable() { public void run () {
          t.scrollRecToVisible(new Rectangle (t.getHorizonalScrollBar().getValue(), 
          t.getDocument().getLength(), rows, cols)); }} ); 
    } catch (Exception e) { /* handle exception */ }
  }
}
//in main
AutoScrollTextArea a = new AutoScrollTextArea (15, 5);
JPanel panel = new JPanel();
panel.add(a.getScrollPane());
//in guiThread
if (a.isAtBottom())
{
  //append text
  a.scrollToBottom();
}
else
  //append text

I have an HP G60t-200 an recently my scroll bar is sticking. Cannot scroll down.

This question has already been answered. Start a new discussion instead.