Java 实时输出到jTextArea

Java 实时输出到jTextArea,java,user-interface,refresh,real-time,jtextarea,Java,User Interface,Refresh,Real Time,Jtextarea,我有一些代码需要几分钟来处理,它必须连接到web上,每个字符串都是一个长数组,每个字符串都是一个url。我想让它在每次连接时都能刷新jtextarea,这样用户就不会盯着一个空白页面看,这个页面看起来冻结了20分钟,或者不管需要多长时间。下面是一个我尝试过但没有成功的例子: try { ArrayList<String> myLinks = LinkParser.getmyLinksArray(jTextArea1.getText());

我有一些代码需要几分钟来处理,它必须连接到web上,每个字符串都是一个长数组,每个字符串都是一个url。我想让它在每次连接时都能刷新jtextarea,这样用户就不会盯着一个空白页面看,这个页面看起来冻结了20分钟,或者不管需要多长时间。下面是一个我尝试过但没有成功的例子:

try {
            ArrayList<String> 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);
        }
试试看{
ArrayList myLinks=LinkParser.getmyLinksArray(jTextArea1.getText());
用于(字符串s:MyLink){
jTextArea2.append(LinkChecker.checkFileStatus)+“\n”);
}
}捕获(IOEX异常){
showMessageDialog(jTextArea1,“解析错误”,“解析错误”,JOptionPane.Error\u消息);
Logger.getLogger(MYView.class.getName()).log(Level.SEVERE,null,ex);
}

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

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

您还希望限制在gui线程上执行的操作,以避免gui变得迟钝,因此,如果checkFileStatus非常耗时,请在run方法之外执行它,并将结果存储在最终的局部变量中,然后只需在run()代码中访问该变量。

swing/awt是一个单线程库,因此一旦显示组件,仅仅改变它的外观是不能正常工作的。您需要更改GUI线程上的组件,而不是从您的线程。要执行此操作,请包装使用SwingUtilities.invokeLater更新组件的任何代码。。。如

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

此外,您还希望限制在gui线程上执行的操作,以避免gui变得迟钝,因此如果checkFileStatus非常耗时,请在run方法之外执行它,并将结果存储在最终的局部变量中,然后只访问run()代码中的变量。

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

final ArrayList<String> myLinks = //... (new Thread() { public void run(){ for (String s : myLinks) { try{ final String result = LinkChecker.checkFileStatus(s) + "\n"; SwingUtilities.invokeLater(new Runnable(){ public void run(){ jtextArea2.append(result); } }); }catch(IOException error){ // handle error } } } }).start(); 最终阵列列表MyLink=/。。。 (新线程() { 公开募捐{ 用于(字符串s:MyLink){ 试一试{ 最终字符串结果=LinkChecker.checkFileStatus+“\n”; SwingUtilities.invokeLater(新的Runnable(){ public void run(){ jtextArea2.追加(结果); } }); }捕获(IOException错误){ //处理错误 } } } }).start(); 编辑
已经指出,JTextArea的append函数实际上是线程安全的(与大多数Swing函数不同)。因此,对于这种特殊情况,不需要通过invokeLater对其进行更新。但是,您仍应在后台线程中进行处理,以允许GUI更新,因此代码如下:

final ArrayList<String> myLinks = //... (new Thread() { public void run(){ for (String s : myLinks) { try{ jtextArea2.append(LinkChecker.checkFileStatus(s) + "\n"); }catch(IOException error){ // handle error } } } }).start(); 最终阵列列表MyLink=/。。。 (新线程() { 公开募捐{ 用于(字符串s:MyLink){ 试一试{ jtextArea2.append(LinkChecker.checkFileStatus)+“\n”); }捕获(IOException错误){ //处理错误 } } } }).start();
但是,对于几乎所有修改Swing对象的其他操作,您都需要使用invokeLater(以确保在GUI线程中进行修改),因为几乎所有Swing函数都不是线程安全的。

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

final ArrayList<String> myLinks = //... (new Thread() { public void run(){ for (String s : myLinks) { try{ final String result = LinkChecker.checkFileStatus(s) + "\n"; SwingUtilities.invokeLater(new Runnable(){ public void run(){ jtextArea2.append(result); } }); }catch(IOException error){ // handle error } } } }).start(); 最终阵列列表MyLink=/。。。 (新线程() { 公开募捐{ 用于(字符串s:MyLink){ 试一试{ 最终字符串结果=LinkChecker.checkFileStatus+“\n”; SwingUtilities.invokeLater(新的Runnable(){ public void run(){ jtextArea2.追加(结果); } }); }捕获(IOException错误){ //处理错误 } } } }).start(); 编辑
已经指出,JTextArea的append函数实际上是线程安全的(与大多数Swing函数不同)。因此,对于这种特殊情况,不需要通过invokeLater对其进行更新。但是,您仍应在后台线程中进行处理,以允许GUI更新,因此代码如下:

final ArrayList<String> myLinks = //... (new Thread() { public void run(){ for (String s : myLinks) { try{ jtextArea2.append(LinkChecker.checkFileStatus(s) + "\n"); }catch(IOException error){ // handle error } } } }).start(); 最终阵列列表MyLink=/。。。 (新线程() { 公开募捐{ 用于(字符串s:MyLink){ 试一试{ jtextArea2.append(LinkChecker.checkFileStatus)+“\n”); }捕获(IOException错误){ //处理错误 } } } }).start();
但是,对于几乎所有修改Swing对象的其他操作,您都需要使用invokeLater(以确保在GUI线程中进行修改),因为几乎所有Swing函数都不是线程安全的。

您需要调查线程及其在Swing中的情况。任何影响或使用Swing中GUI组件的操作都必须在名为的特殊线程上完成

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

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