Pergunta

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());
    }
}
Foi útil?

Solução

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);

    }
});

Outras dicas

@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.

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);
    }
}
scrollBar.getValue()==scrollBar.getMaximum()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top