在执行其他方法时在单独的线程上更新 GUI [英] Updating GUI on separate thread while other method is executing

查看:20
本文介绍了在执行其他方法时在单独的线程上更新 GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个 GUI,它有几个按钮和一个用于输出的 JTextArea.我下面有一些执行函数并更新 TextArea 的代码,但是在执行该函数之前,我希望使用字符串Processing..."更新 TextArea,只是为了给用户应用程序正在运行的某种想法,因为函数需要一段时间才能执行.

I have a GUI that I have developed that has a couple of buttons and a JTextArea for output. I have some code below that executes a function and updates the TextArea, however before the function is executed I would like the TextArea to be updated with the string "Processing...", just to give the user some kind of idea that the application is working as the function takes a while to execute.

目前这段代码没有更新 GUI 元素,我明白为什么.GUI 没有机会在更改 TextArea 的两个命令之间重新绘制,因此永远不会显示正在处理..."字符串.如何更改代码,以便在 Main.featureAnalysisTop() 函数执行之前更新 GUI 元素?

At the moment this code doesn't update the GUI element and I understand why. The GUI doesn't get a chance to repaint in between the two commands that change the TextArea, so the "processing..." string is never displayed. How do I change the code so that the GUI element updates before the Main.featureAnalysisTop() function executes?

if(e.getActionCommand().equals("Extract Features"))
            {                   
                featuresTextArea.setText("Processing...");
                int nFeatures = nFeatureSlider.getValue(); 
                Main.featureAnalysisTop(nFeatures);

                featuresTextArea.setText("");
                ArrayList<String> featureList = Main.getFeatureList();

                for(String str : featureList)
                {
                        featuresTextArea.append(str + "\n");
                }

GUI 在我的 main 方法中使用以下代码执行.

The GUI is executed in my main method using the following code.

public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    gui = new GUI2();
                    gui.setLocationRelativeTo(null);
                    gui.frmNeuralNetwork.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

推荐答案

在执行其他方法时在单独的线程上更新 GUI

Updating GUI on separate thread while other method is executing

这是Swing Woker 类的工作,它允许您创建一个在后台运行的单独线程,并让您相应地更新您的 GUI.

That's a job for the Swing Woker class, which allows you to create a separate thread that runs in the background and lets you update your GUI accordingly.

例如,我做了一个简单的例子来完成你想要做的事情.

For example, I made a simple example that accomplishes what you're trying to do.

首先,我们创建 GUI 并将 ActionListener 添加到我们的 JButton 中,它会在更新 JTextArea<后启动我们的 Swing Worker/code> 的文本到 processing...,因为您正在尝试这样做,并且在 5 秒后(模拟您长时间运行的任务)它更新为 I'm done!代码>.

First we create the GUI and add an ActionListener to our JButton where it starts our Swing Worker after updating the JTextArea's text to processing... as you were trying to do it and after 5 seconds (which simulates your long running task) it updates to I'm done!.

您可以尝试并相应地更改代码.

You can try it and change the code accordingly.

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class TextAreaUpdater {
    private JFrame frame;
    private JTextArea area;
    private JButton button;
    private SwingWorker<String, String> worker;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TextAreaUpdater()::createAndShowGui);
    }

    private void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());

        area = new JTextArea(10, 30);

        button = new JButton("Update!");
        button.addActionListener(listener);

        worker = new SwingWorker<String, String>() {
            @Override
            protected String doInBackground() throws Exception {
                try {
                    Thread.sleep(5000); //Simulates long running task
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "I'm done!"; //Returns the text to be set on the JTextArea
            }

            @Override
            protected void done() {
                super.done();
                try {
                    area.setText(get()); //Set the textArea the text given from the long running task
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        };

        frame.add(area, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private ActionListener listener = (e -> {
        area.setText("Processing...");
        worker.execute(); //Initializes long running task
    });
}

参考资料:

这是另一个使用 SwingWorker 的示例:打开 jdialog 后更新 jlabel 文本

Here's another example that uses SwingWorker: update jlabel text after opening jdialog

希望能帮到你

这篇关于在执行其他方法时在单独的线程上更新 GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆