[英]Lazy loading of jList in Swing with SwingWorker needs Thread.sleep()
I try to load content of a JList in Swing dynamically so that only shown content is loaded from somewhere (database, filesystem, rpc call). 我尝试在Swing中动态加载JList的内容,以便仅从某处(数据库,文件系统,rpc调用)加载显示的内容。 The code below does not implement this actions because it is not really important for showing the problem.
下面的代码不执行此操作,因为它对于显示问题并不十分重要。
So I implement my own list model class: 因此,我实现了自己的列表模型类:
class ServiceListModel extends AbstractListModel {
private final static int MYSIZE = 500;
private final List<String> delegate = new ArrayList<String>();
public ServiceListModel() {
// Init with dummy content
for(int i=0;i<MYSIZE;i++) {
delegate.add("Loading...");
}
}
@Override
public int getSize() {
return delegate.size();
}
@Override
public Object getElementAt(int index) {
new DoSomeThingClass(index, this).execute();
}
private class DoSomeThingClass extends SwingWorker<String, String> {
private int index;
private ServiceListModel model;
public DoSomeThingClass(int index, ServiceListModel model) {
this.index = index;
this.model = model;
}
@Override
protected String doInBackground() throws Exception {
System.out.println("BACKGROUND: " + index);
// Do some stuff for updating content in JList
return "";
}
@Override
protected void process(java.util.List<String> list) {
for(String s: list) {
}
}
@Override
protected void done() {
System.out.println("INDEX: " + index);
}
}
}
Set the model in JList: 在JList中设置模型:
jList1.setModel(new ServiceListModel());
The problem is now that if I scroll quickly to the end of the JList content still all values are computed in method getElementAt(index)
and not only the end of JList content. 现在的问题是,如果我快速滚动到JList内容的末尾,那么所有值仍然在方法
getElementAt(index)
中计算,而不仅是JList内容的末尾。 All index values are displayed in system out console. 所有索引值都显示在系统输出控制台中。
To solve the problem it is needed to add a Thread.sleep(20) in getElementAt(index)
before calling Swing Worker class. 为了解决该问题,需要在调用Swing Worker类之前在
getElementAt(index)
添加Thread.sleep(20)。
Question: 题:
Why did I need this Thread.sleep() call and is this not only a hack? 为什么我需要这个Thread.sleep()调用,这不仅是hack吗? I did not understand why
getElementAt(index)
is called for all values. 我不明白为什么要为所有值调用
getElementAt(index)
。
PS: The list model is only passed to swing worker class because of updating values which are calculated in doInBackground()
method. PS:由于更新了在
doInBackground()
方法中计算的值,因此列表模型仅传递给swing工人类。
The getElementAt() is called several times because the size of the list is specified for 500 elements, and the list iterates over those elements. 由于为500个元素指定了列表的大小,因此getElementAt()被多次调用,并且列表在这些元素上进行迭代。
Source from javax.swing.plaf.basic.BasicListUI: 来自javax.swing.plaf.basic.BasicListUI的源:
for(int index = 0; index < dataModelSize; index++) {
Object value = dataModel.getElementAt(index);
...
However I recommend to have a look at Glazed Lists . 但是,我建议看看“ 釉面表” 。 If you want to update elements at a given index you can use EventList.
如果要更新给定索引处的元素,则可以使用EventList。
"...You can populate your EventList from one thread and read it from another. For GUI applications, you can populate your EventList on a background thread while safely browsing it using the user-interface thread.." “ ...您可以从一个线程填充EventList并从另一个线程读取它。对于GUI应用程序,您可以在后台线程中填充EventList,同时使用用户界面线程安全地浏览它。
Look at the tutorial , the issues browser might be a similar use case to yours. 查看教程 ,问题浏览器可能与您的用例相似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.