5

我的代码如下:

class SimplifiedClass extends JApplet {

    private JTextArea outputText;
    // Lots of methods
    public void DoEverything() {
        String output = "";
        for(int i = 0; i <= 10; i++) {
            output += TaskObject.someLongTask(i);
            outputText.setText(output);
        }
    }
}

但是,当调用 setText 时,它不会在每次循环迭代后更新文本区域,而是仅在任务的所有运行完成后才更新文本。为什么会发生这种情况,我该如何解决?

4

6 回答 6

4
private JTextArea outputText = new JTextArea();

public void DoEverything() {
    String output = "";
    for(int i = 0; i <= 10; i++) {
        output += TaskObject.someLongTask(i);
        appendNewText(output);
    }
}

public void appendNewText(String txt) {
  SwingUtilities.invokeLater(new Runnable() {
     public void run() {
        outputText.setText(outputText.getText + txt);
       //outputText.setText(outputText.getText + "\n"+ txt); Windows LineSeparator
     }
  });
}
于 2011-07-21T10:22:01.243 回答
2

您可能正在使用 Swing 线程,该线程正在等待您的代码执行,然后才能更新 UI。尝试为该循环使用单独的线程。

public void DoEverything() {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      String output = "";
      for(int i = 0; i <= 10; i++) {
        output += TaskObject.someLongTask(i);
        outputText.setText(output);
      }
    }
  });
}
于 2011-07-21T10:11:20.703 回答
2

您正在使用称为初始线程的摇摆基本线程。请改用工作线程。尝试将 SwingWorker 用于工作线程。

有关更多详细信息,请访问以下链接: http ://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html

于 2012-09-24T06:55:41.197 回答
1

正如帖子所说,重要的是不要阻塞 EDT(事件调度线程)。在我下面的示例中,实际工作从 EDT 线程开始,因为它是从按钮单击 ActionListener 开始的。我需要用一个单独的线程包装它,以便它与事件调度线程分开。因此 EDT 没有被阻塞。

另请注意,从单独的线程更新 UI 时需要 SwingUtilities.invokeLater()。下面的代码示例从我的原始代码中进行了一些简化。我实际上使用多个线程并行执行多个任务,并且在每个线程中调用 updateProgress() 通过附加最新状态来更新 TextArea。

完整的源代码在这里:https ://github.com/mhisoft/rdpro/blob/master/src/main/java/org/mhisoft/rdpro/ui/ReproMainForm.java

btnOk.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    //Don't block the EDT, wrap it in a seperate thread
    DoItJobThread t = new DoItJobThread();
    t.start();

  } 
});


class DoItJobThread extends Thread {
    @Override
    public void run() {
       //do some task 
       // output the progress
       updateProgress();    
    }
}


public void updateProgress(final String msg) {
    //invokeLater()
    //This method allows us to post a "job" to Swing, which it will then run
    // on the event dispatch thread at its next convenience.

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // Here, we can safely update the GUI
            // because we'll be called from the
            // event dispatch thread
            outputTextArea.append(msg);
            outputTextArea.setCaretPosition(outputTextArea.getDocument().getLength());
            //labelStatus.setText(msg);
        }
    });

}
于 2014-11-27T04:53:01.243 回答
0

在自己的线程中运行 DoEverything() 的主体:

class SimplifiedClass extends JApplet {

    private JTextArea outputText;
    // Lots of methods
    public void DoEverything() {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                String output = "";
                for(int i = 0; i <= 10; i++) {
                    output += TaskObject.someLongTask(i);
                    outputText.setText(output);
                }
            }
        }
    }
}
于 2021-06-04T06:01:08.877 回答
-1

尝试在 outputText.setText(output) 之后使用 outputText.validate()

我也为我的程序尝试了这个,它是相似的。出于某种原因,使用Thread.sleep(delay)直接跟随 a outputText.setText("dsfgsdfg"),即使使用 aoutputText.validate()也不允许用户查看输出。这是最奇怪的事情。就好像在setText尝试调用方法之后读取代码一样。然后点击 sleep 方法,这一切都下地狱了。

于 2012-05-17T23:53:42.190 回答