问题
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());
}
}
回答1:
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);
}
});
回答2:
@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.
回答3:
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);
}
}
回答4:
scrollBar.getValue()==scrollBar.getMaximum()
来源:https://stackoverflow.com/questions/12916192/how-to-know-if-a-jscrollbar-has-reached-the-bottom-of-the-jscrollpane