从外部 class 和线程调用 Jframe 中的方法来设置标签值

Calling method in Jframe from external class and thread to set label values

我有两个 classes,一个 JFrame 和一个实现 运行nable 的外部 class。外部class我想运行在它自己的线程中直到给出命令停止。我还希望它通过在其 class 中实现的方法在其自己的线程中在后台更新 JFrame 上的值(或者这就是我认为最优雅的方法)。

我制作了一个简单的程序来说明我想做的事情并证明它不起作用。据我了解,从 EDT 外部调用时,JFrame 的值不会更新。我一直在寻找修复程序,这些修复程序说要包装您想要在 invokelater() 调用中更改文本值的代码部分。但是,这仍然不起作用。我真的很困惑,我确信这很简单,我只是不明白为什么这不起作用。

在这个简单的示例中,我在 JFrame 中有一个开始按钮和输出。我实例化我的外部 class,并在按下开始按钮时将其作为 JFrame class 中的线程启动。该线程在外部 class 中并更新输出,直到它达到 5。它通过调用 JFrame 中的一个方法来完成此操作,该方法在输出标签上调用 setText()

JFrame(我将省略自动生成的部分):

package javaapplicationtest;

public class JavaTestForm extends javax.swing.JFrame {

public JavaTestForm() {
    initComponents();
    jtf = new JavaExternClass();
    jtf_thread = new Thread(jtf);
}

/* Method I use outside of this class to update output label */
public void setLabel(int in) {
    final int inf = in;
    System.out.println("Setting output to " + in);

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            output.setText(Integer.toString(inf));
        }
    });
}

/* Start button is pressed */
private void startActionPerformed(java.awt.event.ActionEvent evt)   {                                      
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            jtf_thread.start();
        }
    });
}   

/* Main entry */
public static void main(String args[]) {
    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new JavaTestForm().setVisible(true);
        }
    });
}

/* External class */
private JavaExternClass jtf;
private Thread jtf_thread;

我的外部 Class:

package javaapplicationtest;

import java.util.logging.Level;
import java.util.logging.Logger;

public class JavaExternClass implements Runnable {    
    public void run() {
        gui = new JavaTestForm();
        for (int i = 0; i < 4; i++) {
            gui.setLabel(i); // Call method to set form output
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(JavaTestForm.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private JavaTestForm gui;
}

在创建 JavaExternClass 的新实例时,您正在创建一个新实例 JavaTestForm...这怎么还没有以 WhosebugException 结束,这超出了我的理解时刻,但 "other" 问题是,JavaExternClassJavaTestForm 的实例与 main 中创建的实例无关,后者实际上是 UI在屏幕上。

与其让 JavaExternClass 创建 JavaTestForm 的新实例,不如将 JavaTestForm 的引用传递给它...

public class JavaExternClass implements Runnable {   
    private JavaTestForm gui;
    public JavaExternClass(JavaTestForm gui) {
        this.gui = gui;

现在,当涉及到这些事情时,我陷入困境,但是,我不想将 classes 传递给其他具有其他功能的 classes收件人不应该知道或无法访问,没有什么比一些 class 一些删除所有组件更糟糕的了!

相反,我会创建一个 interface,它描述了 JavaExternClass 想要执行的操作,并在 JavaTestForm 上实现了这个 class,从而只公开JavaExternClass 期望的功能,仅此而已。

您可能还想看看 Concurrency in Swing and Initial Threads