实时输出到jTextArea

我有一些代码,需要花费几分钟来处理,它必须连接到Web上的长数组中的每个字符串,每个字符串是一个url。 我希望这样做,以便每次连接时,都应该刷新jtextarea,这样用户就不会盯着看起来冻结20分钟的空白页面。 或者需要多长时间。 这是我尝试过的东西的一个例子:

try { ArrayList myLinks = LinkParser.getmyLinksArray(jTextArea1.getText()); for (String s : myLinks) { jTextArea2.append(LinkChecker.checkFileStatus(s) + "\n"); } } catch (IOException ex) { JOptionPane.showMessageDialog(jTextArea1, "Parsing Error", "Parsing Error", JOptionPane.ERROR_MESSAGE); Logger.getLogger(MYView.class.getName()).log(Level.SEVERE, null, ex); } 

问题是您需要异步执行计算。 您应该创建一个执行计算的后台线程,然后使用SwingUtilities.invokeLater更新JTextArea。

 final ArrayList  myLinks = // ...
 (新线程()
 {
     public void run(){
         for(String s:myLinks){
            尝试{
                final String result = LinkChecker.checkFileStatus(s)+“\ n”;
                SwingUtilities.invokeLater(new Runnable(){ 
                     public void run(){    
                       jtextArea2.append(结果);
                     }
                 });
              } catch(IOException错误){
                 //处理错误
              }
         }
     }
 })。开始();

编辑
有人指出,JTextArea的追加函数实际上是线程安全的(与大多数Swing函数不同)。 因此,对于这种特殊情况,没有必要通过invokeLater更新它。 但是,您仍然应该在后台线程中进行处理,以便允许GUI更新,因此代码为:

 final ArrayList  myLinks = // ...
 (新线程()
 {
     public void run(){
         for(String s:myLinks){
            尝试{
                jtextArea2.append(LinkChecker.checkFileStatus(s)+“\ n”);
              } catch(IOException错误){
                 //处理错误
              }
         }
     }
 })。开始();

但是,对于修改Swing对象的几乎任何其他操作,您将需要使用invokeLater(以确保在GUI线程中进行修改),因为几乎所有Swing函数都不是线程安全的。

您需要调查线程及其与 Swing中GUI更新的关系 。 在Swing中影响或使用GUI组件的任何事情都必须在称为事件调度线程(EDT)的特殊线程上完成。

如果你的代码片段,如果它冻结了GUI,我想它正在EDT中运行。 在EDT上执行长时间运行将使GUI无响应,因为在长时间运行的进程使用该线程时无法进行进一步的更新。

有一个名为SwingWorker的辅助类,它允许您将长时间运行的计算卸载到后台线程,然后在GUI线程完成时对其进行更新。 SwingWorker负责管理GUI线程和后台线程之间的上下文切换。 您还可以显示进度条以让用户知道长时间运行的进程的状态,以便他们知道您的应用程序没有挂起。

swing / awt是一个单线程库,因此一旦显示一个组件,只是更改它的外观将无法正常工作。 您需要更改GUI线程上的组​​件,而不是从您的线程更改。 为此,请使用SwingUtilities.invokeLater包装任何更新组件的代码

 SwingUtilities.invokeLater(new Runnable() { public void run() { jTextArea2.append(LinkChecker.checkFileStatus(s) + "\n"); } }); 

你也希望限制你在gui线程上做的事情以避免gui变得迟钝,所以如果checkFileStatus很耗时,在run方法之外执行它并将结果存储在最终的局部变量中,并且只需访问变量run()代码。