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 (e.g. 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.