java 为什么我的 JTextArea 没有更新?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6774414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:13:52  来源:igfitidea点击:

Why is my JTextArea not updating?

javaswingconcurrencyjtextareaevent-dispatch-thread

提问by Macha

I have code as follows:

我有如下代码:

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

However, instead of updating the text area after each iteration of the loop when setText is called, it appears to only update the text when all the runs of the task are done. Why does this happen, and how can I resolve it?

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

采纳答案by Mika T?htinen

You're probably using the Swing thread which is waiting for your code to execute before it can update the UI. Try using a separate thread for that loop.

您可能正在使用 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);
      }
    }
  });
}

回答by mKorbel

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

回答by user1676876

You are using swing basic threads called initial threads. Use worker threads instead. Try using SwingWorker for worker threads.

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

For further details, go through the following link: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html

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

回答by Tony

As the post said it is important not to block the EDT (the Event Dispatch Thread). In my exmaple below the actual work starts from the EDT thread as it is from a button click ActionListener. I need to wrap it with a separate thread so it is separated from the Event Dispatch Thread. Thus the EDT is not blocked.

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

Also note you need to SwingUtilities.invokeLater() when update the UI from a separate Thread. The code example below is simplified a little from my original code. I am actually performing multiple tasks in parallel using multiple threads and in each of those thread the updateProgress() is called to update the TextArea by appending the latest status.

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

Full source code is here: https://github.com/mhisoft/rdpro/blob/master/src/main/java/org/mhisoft/rdpro/ui/ReproMainForm.java

完整源代码在这里: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);
        }
    });

}

回答by Alex

Try using outputText.validate() after outputText.setText(output)

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

I tried this for my program too which is similar. For some reason using the Thread.sleep(delay)directly following a outputText.setText("dsfgsdfg"), even with a outputText.validate()does not allow the user to see the output. It's the strangest thing. It is as if the code is read after the setTextmethod is trying to be invoked. Then hits the sleep method and it all goes to hell.

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