java - 多线程Swing程序中频繁调用setText()

标签 java multithreading swing

我有一个 Swing 程序,其中的工作在非 Swing 线程中持续进行。它经常需要更新 JTextPane —— 每秒更新很多次。我意识到 setText() 需要从事件调度线程内部调用,但我不知道如何让这一切顺利发生。

下面的最小完整示例与我所能得到的一样接近,使用了 PipedInputStream/PipedOutputStream 对,但这似乎每秒钟左右更新一次屏幕。我不确定是什么导致了这么长时间。

import java.awt.event.*;
import javax.swing.*;
import java.io.*;

public class TextTest extends JFrame {
    private JTextPane out = new JTextPane();
    private PipedInputStream pIn = new PipedInputStream();
    private PrintWriter pOut;

    public TextTest() {
        try {
            pOut = new PrintWriter(new PipedOutputStream(pIn));
        }
        catch (IOException e) {System.err.println("can't init stream");}

        add(new JScrollPane(out));
        setSize(500, 300);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        // Start a loop to print to the stream continuously
        new Thread() {
            public void run() {
                for (int i = 0; true; i++) {
                    pOut.println(i);
                }
            }
        }.start();

        // Start a timer to display the text in the stream every 10 ms
        new Timer(10, new ActionListener() {
            public void actionPerformed (ActionEvent evt) {
                try {
                    if (pIn.available() > 0) {
                        byte[] buffer = new byte[pIn.available()];
                        pIn.read(buffer);
                        out.setText(out.getText() + new String(buffer));
                    }
                }
                catch (IOException e) {System.err.println("can't read stream");}
            }
        }).start();
    }

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

我是不是执行错了?关于如何从 EDT 外部持续更新 JTextPane,我的想法是否完全错误?

最佳答案

setText() “方法是线程安全的,尽管大多数 Swing 方法不是。有关更多信息,请参阅 How to Use Threads。”

附录:供引用,这里有一些 other approaches更新 EDT。另一件需要注意的事情是 javax.swing.Timer 的 Action 事件处理程序。在 EDT 上执行。这是我的变体:

import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.text.DefaultCaret;

public class TextTest extends JFrame {

    private JTextArea out = new JTextArea();
    private PipedInputStream pIn = new PipedInputStream();
    private PrintWriter pOut;

    public TextTest() {
        try {
            pOut = new PrintWriter(new PipedOutputStream(pIn));
        } catch (IOException e) {
            System.err.println("can't init stream");
        }

        DefaultCaret caret = (DefaultCaret) out.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

        add(new JScrollPane(out));
        setSize(300, 500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        // Start a loop to print to the stream continuously
        new Thread() {

            public void run() {
                for (int i = 0; true; i++) {
                    pOut.println(i);
                }
            }
        }.start();

        // Start a timer to display the text in the stream every 10 ms
        new Timer(10, new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                try {
                    out.append(String.valueOf((char) pIn.read()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

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

关于java - 多线程Swing程序中频繁调用setText(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4138996/

相关文章:

java - 管理流使用期间的内存使用情况

Android:在后台同步远程数据库最流畅的方法是什么?

java - JPanel 的空指针异常

java - 当我尝试使用 Canvas 显示背景图像时出现问题

java - ScrollPane 与 PaintSurface 一起使用

java - 当依赖 SimplePizzaFactory 时,PizzaStore 如何接受不同的工厂?

java - 图像作为 TabIndicator

c# - Thread.Sleep 会影响 ThreadState 吗?

c++ - Oracle 的 Pro*C 从多线程访问

java - Android 用户界面编码错误