使用SwingWorker在Swing中延迟加载jList需要Thread.sleep()

时间:2013-12-18 12:28:29

标签: java multithreading swing

我尝试动态加载Swing中JList的内容,以便只从某处(数据库,文件系统,rpc调用)加载显示的内容。下面的代码没有实现此操作,因为它对于显示问题并不重要。

所以我实现了自己的列表模型类:

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); 
    }
  }
}

在JList中设置模型:

jList1.setModel(new ServiceListModel());

现在的问题是,如果我快速滚动到JList内容的末尾,仍然会在方法getElementAt(index)中计算所有值,而不仅仅是JList内容的结尾。 所有索引值都显示在system out console中。

要解决此问题,需要在调用Swing Worker类之前在getElementAt(index)中添加Thread.sleep(20)。

问题:

为什么我需要这个Thread.sleep()调用,这不仅仅是一个黑客攻击吗?我不明白为什么要为所有值调用getElementAt(index)

P.S:列表模型仅传递给swing worker类,因为更新了以doInBackground()方法计算的值。

1 个答案:

答案 0 :(得分:1)

多次调用getElementAt()因为为500个元素指定了列表的大小,并且列表会迭代这些元素。

来自javax.swing.plaf.basic.BasicListUI的来源:

for(int index = 0; index < dataModelSize; index++) {
    Object value = dataModel.getElementAt(index);
...

但我建议您查看Glazed Lists。如果要更新给定索引处的元素,可以使用EventList。

“...您可以从一个线程填充EventList并从另一个线程中读取它。对于GUI应用程序,您可以在后台线程上填充EventList,同时使用用户界面线程安全地浏览它。”

查看tutorial,问题浏览器可能与您的用例类似。