Java Swing多线程和ui冻结

Java Swing多线程和ui冻结,java,swing,swingworker,concurrency,Java,Swing,Swingworker,Concurrency,我想不出这个。使用worker或invokeLater,UI仍然冻结。下载每个文件后,我希望更新JList。但JList仅在踏板返回后更新 代码如下: public class MyUi extends javax.swing.JFrame{ ... private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){ SwingUtilities.invokeLater(new Runnable

我想不出这个。使用worker或invokeLater,UI仍然冻结。下载每个文件后,我希望更新JList。但JList仅在踏板返回后更新

代码如下:

public class MyUi extends javax.swing.JFrame{
    ...

   private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){

      SwingUtilities.invokeLater(new Runnable() {
         //To get out of the event tread
         public void run() {
            dl(); 
         }
       });
   }

   private void dl(){
      ...
      //ini and run the download class
      Download myDownload = new Download();
      myDownload.doDownload(myDlList);
   }

   public void updateJlist(String myString){

       myModel.addElement(myString);
       jList1.repaint();
   }

}

public class Download{
...

  public void doDownload(String[] fileName){
      for(int i=0; i<fileName.length; i++){
         ...//download action...
         //for my jList1 to be updated after each file.
         MyUi.updateJlist(fileName[i]);
      }
   }

}
公共类MyUi扩展了javax.swing.JFrame{
...
私有void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
SwingUtilities.invokeLater(新的Runnable(){
//从事件中脱身
公开募捐{
dl();
}
});
}
私有void dl(){
...
//并运行下载类
下载myDownload=新下载();
myDownload.doDownload(myDlList);
}
public void updatejslist(字符串myString){
myModel.addElement(myString);
jList1.repaint();
}
}
公共类下载{
...
public void doDownload(字符串[]文件名){

对于(int i=0;i在后台线程上下载该文件,并在
Runnable
中仅包装
updatejslist()

会更可靠


附录:@mre指出,
SwingWorker
也可以很容易地报告临时结果,如图所示。

invokeLater
做的与您期望的完全相反-它在EDT上运行操作,这解释了该行为。

我创建了一个WorkerThread类,负责线程和GUI当前/主线程阅读。我已经将我的GUI应用程序放入WorkerThread的construct()方法中,当一个事件触发以启动XXXServer时,所有线程都被激活,GUI在不冻结的情况下顺利工作。看一看

/***Action Event**@参见java.awt.Event.ActionListener#actionPerformed(java.awt.Event.ActionEvent)*/

已执行的公共无效行动(行动事件ae){ log.info(“actionPerformed begin…”+ae.getActionCommand())


}

在后台运行下载只需fin即可,我不需要包装UpdateList()。对于SwingWorker,我需要阅读更多关于它的内容并执行测试。我不完全理解它。谢谢!我很高兴它能工作,但我仍然希望从非EDT线程更新GUI。如果您需要有关
SwingWorker
@marcb的帮助,请毫不犹豫地发布一个问题。从EDT更新列表显然是错误的,即使它出现了ars正在工作。您必须访问EDT上Swing组件的所有属性(包括任何模型),该规则也不例外。我已删除我的注释“最终代码:”因为我现在意识到,即使它工作得很好,这也是一个很大的错误和糟糕的编码。我会继续阅读SwingWorker,清理我的代码,然后我会发回我的问题和担忧。感谢支持。
try {
    if (ae.getActionCommand().equals(btnStart.getText())) {
         final int portNumber = 9990;
         try {

             WorkerThread workerThread = new WorkerThread(){
                public Object construct(){

                    log.info("Initializing the Server GUI...");
                    // initializing the Server
                     try {
                        xxxServer = new XXXServer(portNumber);
                        xxxServer.start();
                        btnStart.setEnabled(false);                             
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
                        e.printStackTrace();
                    }
                    return null;
                }
            };workerThread.start();
            } catch (Exception e) {
                log.info("actionPerformed() Start button ERROR..." + e.getMessage());
                e.printStackTrace();
         }


    } else if (ae.getActionCommand().equals(btnStop.getText())) {
        log.info("Exit..." + btnStop.getText());
        closeWindow();
    }

} catch (Exception e) {
    log
        .info("Error in ServerGUI actionPerformed==="
            + e.getMessage());
}