Java Tips Weblog

  • Blog Stats

    • 2,240,529 hits
  • Categories

  • Archives

Smart Scrolling

Posted by Rob Camick on March 3, 2013

There may be times when you have a component in a JScrollPane and data is dynamically added to this component. Normally, you would like the viewport to scroll to the bottom automatically as new data is added so you can see the most recent data. However, there may also be times when you are viewing data somewhere else in the viewport and you don’t want the scrolling to happen automatically. Supporting both of these of these requirement would require a scrollpane to support smart scrolling.

A simple definition for smart scrolling in this situation would be:

  • when the viewport is at the bottom and new data is added, then automatically scroll the viewport to the bottom
  • when the viewport is not at the bottom and new data is added, then do nothing with the viewport

Maybe not as common, but there may be times when the data is dynamically added at the start of the component. In this case the definition for smart scrolling would be:

  • when the viewport is at the top and new data is added, then do nothing with the viewport
  • when the viewport is not at the top and new data is added, then adjust the viewport to the relative position it was at before the data was added

The SmartScroller class was created to support both types of smart scrolling. In addition, the SmartScroller class supports vertical or horizontal scrolling. The SmartScroller class only requires a couple of properties to be specified when it is created:

  • scroll pane – the scroll pane to monitor
  • scroll direction – monitor vertical or horizontal scrolling. Valid values are:
    • SmartScroller.VERTICAL (default) – monitor scrolling in the vertical direction
    • SmartScroller.HORIZONTAL – monitor scrolling in the horizontal direction
  • viewport position – indicates where the viewport should be positioned to see the dynamically added data. Valid values are:
    • SmartScroller.END (default) – viewport is kept at the end of the scrollpane (ie. the bottom for vertical scrolling and the right for horizontal scrolling)
    • SmartScroller.START – viewport is kept at the start of the scrollpane (ie. the top for vertical scrolling and the left for horizontal scrolling)

For example, in the situation when a JTextArea is used as a simple display console, you can create the SmartScroller by using code like:

JTextArea textArea = new JTextArea(...);
JScrollPane scrollPane = new JScrollPane( textArea );
new SmartScroller( scrollPane );

This convenience constructor will default to vertical scrolling and the viewport will be positioned at the bottom. When you want to use horizontal scrolling you need to use the full constructor. For example:

JTable table = new JTable(...);
JScrollPane scrollPane = new JScrollPane( table );
new SmartScroller(scrollPane, SmartScroller.HORIZONTAL, SmartScroller.END);

Thats all there is to using the SmartScroller class. There are no properties to change at runtime. You must create a new SmartScroller for every scrollpane that requires this functionality.

Try the WebStart demo below. The demo allows you to reset the two properties and observe the behaviour of the SmartScroller.

SmartScroller

Although the demo show the usage of a JTextArea and JList you should be able to use the SmartScroller on any scrollpane no matter what component it displays.

Try The Demo

Launch – Using Java™ Web Start (JRE 6+ required)

Get The Code

SmartScroller.java

16 Responses to “Smart Scrolling”

  1. willemien said

    Hi
    in the sourcecode with this post you do not use the caret option described in
    https://tips4java.wordpress.com/2008/10/22/text-area-scrolling/

    What is the (probably best) way to keep a slider of a JschrollPane at the end of a logger JTextArea?

    also i was wondering
    I have an Swing logger (JDialog, conatining a JscrollPane, containing a JTextPanel) for an process in the main thread and i am wondering what happens if the process adds quicker runnables to the EDT (EventDispachThread, via SwingUtilities, invokeLater() ) than the EDT can process them.

    • Rob Camick said

      This has different functionality than the “Text Area Scrolling” entry. The text area scrolling will reset the scrollpane to the bottom every time new text is added, so that is what you should use if you always want the text at the bottom. This approach does not automatically scroll to the bottom if the user has manually scrolled the scrollpane to look at some other data in the text area.

      The EDT queues all requests. I don’t know what happens it you somehow manage to flood the queue. I would guess the app freezes until all requests can be handled or you get an out of memory exception of some kind.

  2. Mike said

    Thanks for this! I was having issues because I would query the extent property and it wasn’t updating at the same time as maximum updated, you seem to have figured it out.

  3. Bunmi Ogunsan said

    Hi Rob, I know this is an old Thread but it’s helped me tremendously. I’d like to know if in your example, the text component had a buffer and the buffer was full, if there’s any way to make the scrollbar follow (up) after the output text if the scrollbar is not at the bottom.

  4. Mike said

    Hi Rob, I am about to try to use this. Is there a copyright? I will attribute to this site if I can’t find any other way to let people know where I got it. Thanks

    • Rob Camick said

      The “About” page says you can use the code however you wish. Good luck.

      • Mike said

        Thank you. I copied the concept to have a dedicated vertical one for a special case. I do not want to confuse later developers who might maintain this with options never used by us at this time. However, I put this link in the comments… if they ever need the more general case.

  5. Anonymous said

    Bravo et merci !

  6. Matthias from Germany. said

    After two hours of searching and experimenting I found this perfect solution! Many Thanks!

  7. Bodo said

    Thanks a lot. Works great!
    Changed the options & corresponding code to two small enums inside the class, so you can’t use invalid ints as input anymore.
    public enum ScrollDirection
    {
    HORIZONTAL,
    VERTICAL;
    }

    public enum ViewportPosition
    {
    START,
    END;
    }

  8. Tomasz Uzieblo said

    Hello.

    As this webpage is full of brilliant solutions, after long time of private unsuccessful investigations, I decided to ask my question here.

    I’m looking for some specific solution for scrolling JTextComponent (in my case JEditorPane component). In my JEditorPane, I display local url (simple html file containing hashtags). When I click on such link, appropriate line is found, but displayed at the very bottom of viewport. What I’d like to achieve is either line containing hashtag to be displayed at first line (when there is enough lines after in the buffer) or to be displayed as close as top of viewport.

    Any idea how to do it? Any suggestions would be deeply appreciated.

    • Rob Camick said

      I never play with a JEditorPane to I don’t know how it works. I guess you would need to find an event that is generated when you click on a link. Then in the event listener you add SwingUtilities.invokeLater() code, so your custom code is executed after the scrolling has finished. Then you would get the current location of the caret (assuming the caret is moved to the new location) and use the “modelToView(…)” method to get the current position of the view. Then you determine where the view is in the viewport and determine if you can scroll the view to the top of the viewport by using the “setViewPosition()” method. A lot of guess work here. If you need more help create a “MCVE” and post the code in a forum so other can look at it.

  9. Stéphane Mottelet said

    Hello,

    SmartScroller works great, however I noticed a small glitch. When the scrollbar is moved by dragging it with the mouse pointer then automatic scrolling is stopped as expected and later on using mouse wheel, pageup or pagedown key also give the desired behavior. However, when using only pageup or pagedown keys or mousewheel, then autoscrolling is not disabled. I have to drag the scrollbar with the mousepointer first to make it work later on. How can I modify the code to allow disabling autoscrolling when using keys or mousewheel ? Thanks for your help and thanks again for the actual version of the code which works already great (compared to other solutions I have tested).

    • Rob Camick said

      The scrolling works fine for me whether I use the pageUp/pageDown, mouseWheel or drag the scrollbar. I can stop/start the scrolling as required. Maybe this is a version/platform issue. I use JDK8 on Windows 7. I don’t have access to test on other platforms so you would need to debug the code yourself to see what is happening.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: