【问题标题】:Swing Worker append text area not executing until after all other threads finishedSwing Worker 追加文本区域直到所有其他线程完成后才执行
【发布时间】:2021-10-29 05:54:54
【问题描述】:

我希望在我的程序运行期间更新一个摆动文本区域。我的程序做了很多复杂的文件处理。

在我的程序中,我有一个文本区域,例如可以使用 writeText("text") 进行更新(方法如下所示)。在 writeText() 方法中,我使用一个简单的 textArea.append() 和一个 swing worker 来执行此操作,但直到所有处理都发生在我的主类中之后它才会更新文本。如何通过实时更新文本区域来使其正常工作,例如 System.out.println() 如何随时将文本发送到控制台。

    public static void writeText(String text) {
            System.out.println("SWING WORKER");
            worker = new SwingWorker<Void, String>() {
                @Override
                protected Void doInBackground() throws Exception {
                    publish(" " + text + "\n");
                    return null;
                }
                
                @Override
                protected void process(List<String> chunks) {
                    textArea.append(chunks.get(chunks.size() - 1));
                    frame.repaint();
                }
                
                @Override
                protected void done() {
                    //textArea.append(" test done\n");
                }
                
            };
            worker.execute();
        }  

我尝试过线程化,现在使用 swing worker,但两次尝试都只在主要复杂方法运行后更新了文本(复制、重命名和子映像出有点东西的文件,基本上我只想用追加更新文本区域() 以便用户知道程序运行时发生了什么)

【问题讨论】:

  • SwingWorker 用于耗时的后台任务,但您使用它来更新文本区域。在 doInBackground 方法中进行文件处理。
  • 考虑发布minimal reproducible example。此外,无需在SwingWorker 的方法process 中调用frame.repaint()
  • 听起来好像有什么东西阻塞了主线程,但如果没有更多上下文就不可能知道是什么。考虑提供一个 minimal reproducible example 来证明您的问题
  • github.com/swimfanbruh/Auto-Pack-Porter 这是 20 天前项目的旧版本。这可以让您了解正在发生的事情。
  • “这可以让您了解正在发生的事情。” 不要链接到可能会消失的外部资源。也不要像@Abra 和MadProgrammer 所建议的那样,将您的时间(以及更重要的是人们提供免费帮助的时间)浪费在除了 minimal reproducible example 之外的任何东西上。减一,因为我怀疑您没有阅读链接的文档。

标签: java swing swingworker


【解决方案1】:

听起来好像有别的东西阻塞了主线程,但如果没有更多上下文,就不可能知道是什么。

重要的是,您正在做的任何长时间运行的工作都在doBackground 方法中完成,以防止事件调度线程被阻塞(并且无法处理新事件,包括绘画请求)。

下面的例子只是简单地逐行读取一个文本文件,并随机延迟发布该行,因此可以将其添加到JTextArea

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.SwingWorker;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea textArea;

        public TestPane() {
            setLayout(new BorderLayout());
            textArea = new JTextArea(40, 40);
            add(new JScrollPane(textArea));

            SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
                @Override
                protected Void doInBackground() throws Exception {
                    try (BufferedReader br = new BufferedReader(new InputStreamReader(TestPane.this.getClass().getResourceAsStream("Script.txt")))) {
                        String text = null;
                        Random rnd = new Random();
                        while ((text = br.readLine()) != null) {
                            publish(text);
                            Thread.sleep(rnd.nextInt(500));
                        }
                    } catch (IOException exp) {
                        exp.printStackTrace();
                        publish("Failed to load script file: " + exp.getMessage());
                    }
                    return null;
                }

                @Override
                protected void process(List<String> chunks) {
                    for (String text : chunks) {
                        textArea.append(text);
                        textArea.append("\n");
                    }
                }
            };

            getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "start");
            getActionMap().put("start", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    worker.execute();
                }
            });
        }

    }
}

您还应该确保阅读Worker Threads and SwingWorker

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多