Swing setText在长循环之前不更新文本

时间:2014-05-22 09:20:33

标签: java swing jlabel

我正在尝试在处理循环之前更新Swing JSLable文本,但它没有更新:

public void actionPerformed(ActionEvent event)
{     
    title.setText("Ready"); // Initialize display
    if (source == uploadButton) {
        int returnVal = fc.showOpenDialog(UserInterface.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File[] files = fc.getSelectedFiles();
            if (files.length < 2) {
                title.setText("<html>Text1</html>"); // Is shown
            } else {
                title.setText("<html>Text2</html>"); // Not displaying, feels like UI is locked here

                for (int i = 0; i < files.length; i++) {
                    filesUploaded.add(uploadFile(files[i]));
                }

                Images imgs = new Images();
                imgs.processImages(filesUploaded); // Some processing loop inside, takes around 0.5~1s
                title.setText("Completed"); // displayed corectly.
            }
        }
    }
}

所以基本上我希望有序列:

Ready
Text2
Completed

但是我得到了这个序列(缺少Text2输出):

Ready
Completed

5 个答案:

答案 0 :(得分:2)

GUI线程被阻止,您应该将这部分代码包装到SwingUtilities.invokeLater

SwingUtilities.invokeLater(new Runnable() {

    for (int i = 0; i < files.length; i++) {
        filesUploaded.add(uploadFile(files[i]));
    }

    Images imgs = new Images();
    imgs.processImages(filesUploaded); // Some processing loop inside, takes around 0.5~1s
    title.setText("Completed"); // displayed corectly.
});

BTW,C风格的for循环在Java中不受欢迎,你应该使用“增强版”构造:

for (File file: files)
  filesUploaded.add (files);

甚至

filesUploaded.addAll(Arrays.asList(files))

答案 1 :(得分:0)

没关系,因为你阻止了GUI线程(在该线程中执行了操作),并且在退出方法之前它不会更新。

寻找&#34;阻止gui线程java&#34;。您会发现经常在actionPerformed中发生。

答案 2 :(得分:0)

Swing适用于Single Threaded Model并且Swing应用程序的线程被称为EDT (EventDispatchThread)它始终建议不要对此线程进行任何繁重的处理,因为它会阻止UI线程,你的UI将会在这段时间内没有回应。我建议将文件上传部分移到一个单独的线程中,以保持您的UI响应。

并使用SwingUtilities.invokeLater从这个单独的线程安排任何与EDT相关的UI工作。

另一种方法可能是使用SwingWorker

答案 3 :(得分:0)

使用SwingWorkerFoxtrot来实施长时间运行的任务。您的长时间运行任务会阻止EDT(事件调度程序线程 - 主Swing线程)和无法执行事件处理后必须执行的重绘事件。

答案 4 :(得分:0)

您应该将这些HTML标记放在其他位置,因为当您将文本放在HTML之外时,它会混淆swing。例如。您应该将开始标记放在准备好的单词之前,将结束标记放在完成的字符串之后。您还应该知道setText方法覆盖元素中的文本。你应该使用:

setText(object.getText()+"Text");

例如

title.setText("<HTML>Ready");
//...
title.setText(title.getText()+"Text2");
//...
title.setText(title.getText()+"Completed</HTML>");

请注意,actionPerformed()方法由管理图形用户界面的事件调度线程调用,并且您将其用于冗长的任务。由于EDT不能用于更新GUI,因此冻结了GUI。改为使用不同的线程:

Thread t=new Thread(new Runnable(){
  public void run(){
    <your code here>
  }
});

此外,如果您正在访问swing,Java建议在事件线程上执行它,就像调用setText()或类似的东西一样:

SwingUtilities.invokeLater(new Runnable(){
  public void run(){
    <your code to access swing>
  }
});