为什么我的JTextArea没有更新?

时间:2011-07-21 10:07:53

标签: java swing concurrency jtextarea event-dispatch-thread

我的代码如下:

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时,不是在循环的每次迭代后更新文本区域,而是在完成任务的所有运行时,它似乎只更新文本。为什么会发生这种情况,我该如何解决?

6 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

正如帖子所说,重要的是不要阻止EDT(Event Dispatch Thread)。在我的下面,实际工作从EDT线程开始,因为它来自按钮单击ActionListener。我需要用一个单独的线程包装它,以便它与Event Dispatch Thread分开。因此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);
        }
    });

}

答案 4 :(得分: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);
                }
            }
        }
    }
}

答案 5 :(得分:-1)

  

尝试在outputText.setText(输出)

之后使用outputText.validate()

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