实时输出到jTextArea

发布于 2024-08-29 20:55:26 字数 631 浏览 10 评论 0原文

我有一些代码需要几分钟才能处理,它必须为长数组中的每个字符串连接到网络,每个字符串都是一个网址。我想让它每次连接时都应该刷新 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);
        }

I have some code which takes a few minutes to process, it has to connect to the web for each string in a long array, each string is a url. I want to make it so that everytime it connects, it should refresh the jtextarea so that the user is not staring into a blank page that looks frozen for 20 min. or however long it takes. here is an example of something i tried and didnt work:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

断爱 2024-09-05 20:55:26

问题是您需要异步执行计算。您应该创建一个执行计算的后台线程,然后使用 SwingUtilities.invokeLater 更新 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();

编辑
有人指出,JTextArea 的追加函数实际上是线程安全的(与大多数 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();

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

The problem is that you need to perform the computation asynchronously. You should create a background thread that performs the computation, and then use SwingUtilities.invokeLater to update the 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();

Edit
It has been pointed out that JTextArea's append function actually is thread safe (unlike most Swing functions). Therefore, for this particular, case it is not necessary to update it via invokeLater. However, you should still do you processing in a background thread so as to allow the GUI to update, so the code is:

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

However, for pretty much any other operation that modifies a Swing object, you will need to use invokeLater (to ensure the modification occurs in the GUI thread), since almost all the Swing functions aren't thread safe.

黑寡妇 2024-09-05 20:55:26

您需要研究线程及其与 GUI 更新的关系 在摇摆中。任何影响或使用 Swing 中 GUI 组件的操作都必须在名为 事件调度线程 (EDT)

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

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

You need to investigate threading and its relationship to GUI updates in Swing. Anything that affects or makes use of GUI components in Swing must done on a special thread called the Event Dispatch Thread (EDT).

If your code snippet, if it's freezing the GUI, I imagine that it is being run in the EDT. Performing a long-running action on the EDT will make the GUI unresponsive, because no further updates can be done while your long-running process is using the thread.

There is a helper class called SwingWorker that allows you to offload long-running computations to a background thread, and then make updates to the GUI thread when it is complete. The SwingWorker looks after the context switches between the GUI thread and the background thread. You can also display progress bars to let the user know the state of the long-running process, so they know your application hasn't hung.

百思不得你姐 2024-09-05 20:55:26

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 is a single threaded library, so once a component is shown, just changing it's appearance won't work correctly. You need to change the component on the GUI Thread, not from your thread. To do this wrap any code that updates a component with SwingUtilities.invokeLater... as in

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

also you want to limit what you do on the gui thread to avoid the gui from becoming sluggish, so if checkFileStatus is time consuming, execute it outside the run method and store the result in a final local variable, and just access the variable in the run() code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文