我有一个JTable
,这是从数据库检索到的大量数据的视图。
出于这个原因,我认为只显示这些数据的一部分(例如前100行),当用户使用JScrollBar
到达JTable的末尾时,JTable
将显示其他行。
所以我正在寻找一种机制,让我知道滚动条何时在JTable的末尾,只有在那一刻,执行另一个查询。而且,当我得到新的List
时,将滚动条位置设置为新查询之前的位置,只是为了"连续性"给用户。
谁能给一些技巧来完成这个任务?
提前感谢
正如您之前看到的,大多数jcomponent都有model
,并且它们是根据它们的模型呈现的。因此,如果您可以访问model
,您就可以访问您的目的所需的事件和数据。
由此可见,JScrollBar
也遵循这一规律,有自己的模型。通过获取这个模型(这是一个BoundedRangeModel
)并添加一个ChangeListener
,您可以创建从数据库检索下一页数据所需的内容。
重要的一点是找到支配JScrollBar
模型的规则。BoundedRangeModel
有一些您可以参考的属性。在这种情况下,其中一些对你很重要:
-
valueIsAdjusting
-
value
-
extent
-
maximum
ValueIsAdjusting
表示我们是否处于改变BoundedRangeModel
范围的过程中。坦率地说,这意味着:scrollBar
是否被拖走了?
其他属性value
, extent
和maximum
可以用来确定ScrollBar
是否达到了范围的末端。如果Scrollbar
到达那里,则是从数据库中检索下一页数据的时间。要表示这种情况,必须应用下面的等式:
value
+ extent
= maximum
下面的代码片段可以澄清上述解释:
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);
}
}
(更新)另一种方法是将AdjustmentListener
添加到垂直的JScrollBar
,并使用事件来获得value
和ValueIsAdjusting
。此外,您必须从JScrollBar
的model
中获得extent
和maximum
。下面的代码片段显示了另一种方法:
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();
}
}
}
});
好运。