简体   繁体   中英

Get and set JScrollBar position in Java Swing

I've a JTable that is a view for a large amount of data retrieved from a database.

For this reason, I thought to show only a part of these data (eg first 100 rows) and, when user reach the end of the JTable with the JScrollBar , the JTable will show other rows.

So I'm looking for a mechanism that lets me know when a scrollbar is at the end of the JTable and only at that moment, perform another query. And, when I get the new List , set the scrollbar position to the one before the new query, just for a "continuity" to the user.

Could anyone give some tips to achieve this task?

Thank you in adance

As you may saw before, most of the JComponents has model s and they are being rendered according to their model. So if you can access the model , you can access the events and the data you need for your purpose.

According to this, JScrollBar also follows this rule and has it's own model. By getting this model (which is a BoundedRangeModel ) and adding a ChangeListener you may create what you want for retrieving next page of data from database.

Important point is to find the rule which is ruling over the JScrollBar model. BoundedRangeModel has some properties to which you can refer. Some of them which are important to you in this case are:

  • valueIsAdjusting
  • value
  • extent
  • maximum

ValueIsAdjusting is the one that indicates are we in the middle of the process of changing the range of BoundedRangeModel or not. To be frank, it means: Is the scrollBar getting dragged?

Other properties value , extent and maximum are the ones you can use to find out whether the ScrollBar reached the end of the range or not. If the Scrollbar reached there, it is the time for retrieving next page of data from database. To indicate this situation the following equation must apply:

value + extent = maximum

Following snippet code may clarify the above explanations:

import java.awt.BorderLayout;

import javax.swing.BoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;

public class LiveJTableDemoFrame extends JFrame {
    private static final int FRAME_HEIGHT = 200;
    private static final int FRAME_WIDTH = 400;
    //
    private JTable table;
    private String[] columnNames;
    private DefaultTableModel tableModel;

    public LiveJTableDemoFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(FRAME_WIDTH, FRAME_HEIGHT);
        //
        columnNames = new String[]{"ID", "A", "B", "C", "D"};
        //
        tableModel = new DefaultTableModel(columnNames, 0); 
        table = new JTable(tableModel);
        //
        final JScrollPane p = new JScrollPane();
        p.setViewportView(table);
        p.getVerticalScrollBar().getModel().addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                BoundedRangeModel scModel = p.getVerticalScrollBar().getModel();
                boolean valueIsAdjusting = scModel.getValueIsAdjusting();
                if(!valueIsAdjusting){
                    if(scModel.getValue() + scModel.getExtent() == scModel.getMaximum()){
                        retrieveData();
                    }
                }
            }
        });
        //
        retrieveData();
        //
        this.setLayout(new BorderLayout());
        this.add(p, BorderLayout.CENTER);
    }

    //Dummy method to simulate retrieving data from database
    private void retrieveData(){
        for (int i = 0; i < 10; i++){
            Object[] rowData = new Object[columnNames.length];
            //
            rowData[0] = tableModel.getDataVector().size();
            rowData[1] = "A";
            rowData[2] = "B";
            rowData[3] = "C";
            rowData[4] = "D";
            //
            tableModel.addRow(rowData); 
        }
        //tableModel.fireTableDataChanged();
    }

    public static void main(String[] args) {
        new LiveJTableDemoFrame().setVisible(true);
    }
}

[UPDATE]

Another way to do this is to add an AdjustmentListener to the vertical JScrollBar and use the event to get the value and ValueIsAdjusting . Also you have to get the extent and maximum from the JScrollBar 's model . Following snippet shows the alternative way:

    final JScrollPane p = new JScrollPane();
    p.setViewportView(table);
    p.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener(){ 
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e) {
            // here the control if vertical scroll bar has reached the maximum value
            if(!e.getValueIsAdjusting()){
                JScrollBar source = (JScrollBar) e.getAdjustable();
                int extent = source.getModel().getExtent();
                int maximum = source.getModel().getMaximum();
                if(e.getValue() + extent == maximum){
                    retrieveData();
                }
            }

        }
    });

Good Luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM