5

I'd like to know if there is a way to know when a JScrollBar (vertical in my case) has reached the bottom of his containing JScrollPane.

At first i have though of using an AdjustmentListener on the scroll bar but i don't know how to interpret the value attribute of the JScrollBar. Also i'm not sure to properly understand what the maximum represents and if i can use with the value to get the information i need.

Edit:

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
    @Override
    public void adjustmentValueChanged(AdjustmentEvent ae) {
        System.out.println("Value: " + scrollPane.getVerticalScrollBar().getValue() + " Max: " + scrollPane.getVerticalScrollBar().getMaximum());
    }
}
nathan
  • 1,031
  • 3
  • 16
  • 32
  • @kleopatra do something whenever the scrollbar reach the bottom of the pane. – nathan Oct 16 '12 at 14:19
  • 1
    Do what thing? Please be more specific when someone asks questions like that. – Andrew Thompson Oct 16 '12 at 14:38
  • @AndrewThompson i though it would not be useful to know what i want to do with this information. The question is more "how can i get this information". – nathan Oct 16 '12 at 14:41
  • 3
    @AndrewThompson occasionally (like right now ;-) I get mad at myself for trying to understand the potentially skewed assumed requirements instead of going out into the last autumn sun ... Nathan: the mere fact that I'm asking might give you a hint that maybe the answer might depend on the use-case and/or listening to the adjustable might not be the right approach in all cases. Won't bother again, the last autumn sun is waiting. – kleopatra Oct 16 '12 at 14:48
  • @kleopatra Have a lovely sunshine. :) – Andrew Thompson Oct 16 '12 at 14:51
  • *"i though it would not be useful to know"* (muses) There's just no accounting for what people think. – Andrew Thompson Oct 16 '12 at 14:53
  • @AndrewThompson i will think about it. – nathan Oct 16 '12 at 15:00
  • @nathan I miss real reason for this question, what is/will be goal ..., becuase I miss consequence with question and answer, maybe is required JScrollBar, maybe with AdjustmentListener, maybe BoundedRangeModel, maybe ChangeListener.... – mKorbel Oct 16 '12 at 15:43
  • @mKorbel i'm writing a chat and need to know when the scroll bar reach bottom or get scrolled up to the lock the message flow or not. – nathan Oct 17 '12 at 07:07
  • @nathan have look at [(topics on both sides)](http://tips4java.wordpress.com/2008/11/08/message-console/) – mKorbel Oct 17 '12 at 07:22

4 Answers4

10

You have to add the extent of the scrollbar to your calculation. I added the code into your code in the example below.

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
    @Override
    public void adjustmentValueChanged(AdjustmentEvent ae) {
        int extent = scrollPane.getVerticalScrollBar().getModel().getExtent();
        System.out.println("Value: " + (scrollPane.getVerticalScrollBar().getValue()+extent) + " Max: " + scrollPane.getVerticalScrollBar().getMaximum());
    }
});

Two alternative implementations (partially reacting to Kleopatra)

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {

    @Override
    public void adjustmentValueChanged(AdjustmentEvent event) {
        JScrollBar scrollBar = (JScrollBar) event.getAdjustable();
        int extent = scrollBar.getModel().getExtent();
        System.out.println("1. Value: " + (scrollBar.getValue() + extent) + " Max: " + scrollBar.getMaximum());

    }
});

Or via the model

scrollPane.getVerticalScrollBar().getModel().addChangeListener(new ChangeListener() {

    @Override
    public void stateChanged(ChangeEvent event) {
        BoundedRangeModel model = (BoundedRangeModel) event.getSource();
        int extent = model.getExtent();
        int maximum = model.getMaximum();
        int value = model.getValue();

        System.out.println("2. Value: " + (value + extent) + " Max: " + maximum);

    }
});
JeroenWarmerdam
  • 392
  • 1
  • 9
3

@StanislavL almost had the correct answer.

Try scrollBar.getValue() == scrollBar.getMaximum() - scrollBar.getVisibleAmount().

To understand why the getVisibleAmount() call is necessary, you must first understand how JScrollBars work. A JScrollBar has 4 values: minimum, maximum, value, and extent. value is the top of the scroll handle itself, and extent is the effective length of the scroll handle. value will never equal maximum unless the scroll handle has a length of 0. To compensate, we must adjust the value we are comparing against by subtracting the length of the scroll handle to get the effective maximum.

This effect is documented here, which misleadingly makes it sound like getMaximum() adjusts the value like it should, but looking closely at the implementation of JScrollBar shows that getMaximum() actually gives us the true maximum, not the effective maximum.

Zeimyth
  • 1,299
  • 12
  • 19
  • 1
    This wonderful one-liner should surely be the answer! A simple answer without Viewports etc. Thanks a lot after almost 2 years! – geisterfurz007 Oct 10 '16 at 13:28
1

By using the viewport of the JScrollPane you can calculate if the viewport is viewing the end of the component.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class ViewPortDemo extends JPanel{

    public ViewPortDemo(){
        super();
        JTree tree = new JTree();
        for(int i =0; i < tree.getRowCount(); i++){
            tree.expandRow(i);
        }

        final JScrollPane pane = new JScrollPane(tree){
            Dimension prefSize = new Dimension(200,150);
            public Dimension getPreferredSize(){
                return prefSize;
            }
        };

        pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {

            @Override
            public void adjustmentValueChanged(AdjustmentEvent e) {
                JViewport vp = pane.getViewport();
                if(vp.getView().getHeight() <= vp.getHeight() + vp.getViewPosition().y){
                    System.out.println("End");
                }
            }
        });

        add(pane);
    }


    public static void main(String[] args){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new ViewPortDemo());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
Nick Rippe
  • 6,345
  • 11
  • 30
-1
scrollBar.getValue()==scrollBar.getMaximum()
StanislavL
  • 55,186
  • 9
  • 58
  • 88
  • 1
    Hum. I already tried to display the value of the *value* property when an adjustment event is fired and it never reaches the maximum value. So i think your condition will never be verified. – nathan Oct 16 '12 at 14:00
  • 1
    by using this code line [isn't neccessary to implements AdjustmentListener](http://stackoverflow.com/a/12707995/714968) – mKorbel Oct 16 '12 at 15:39