3

我整天都在尝试不同的变化,但收效甚微。有人可以帮忙解释我做错了什么吗?我只是线程方面的初学者。

private JTextArea text = new JTextArea();
private JButton button = new JButton("Cancel");
    public StatusFrame() {
        text.setEditable(false);
        this.add(text);
        this.add(button, BorderLayout.EAST);
        this.setSize(new Dimension(150, 100));
        this.setVisible(true);
    }

    public void updateStatus(String textIn) {
        text.setText(textIn);
    }

    public JButton getButton() {
        return button;
    }

在另一堂课中,我正在调用可能需要一段时间才能完成的方法。我希望能够调用 StatusFrame.updateStatus() 方法来让用户了解进度。这就是我所拥有的:

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);

//do something 
    status.update("process 1 completed");
//do something else
    status.updateStatus("Process 2 completed");
}

框架出现,但运行/处理后没有任何代码似乎运行/处理。它只是停止/阻止/某事。但 GUI 仍然处于活动状态

感谢您的任何建议。

PS:我尝试过使用invokeAndWait()方法,但再次不确定我是否以正确的方式进行操作。现在最好快速修复,因为我还没有学到很多关于线程的知识。欢迎任何指示。

4

3 回答 3

7

你有倒退的概念。

这是你的代码

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);

//do something 
    status.update("process 1 completed");
//do something else
    status.updateStatus("Process 2 completed");

您应该在线程中执行长时间运行的代码,并使用 SwingUtilities invokeLater 方法更新 GUI。

someMethod() {
    // prevent GUI from freezing using threads
    final Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    new Thread(r).start();

// inside the StatusFrame
//do something 
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            update("process 1 completed");
        }
    );

 //do something else sometime later
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
             update("Process 2 completed");
        }
    );

我不知道我的回答是否清楚。

  1. 在启动 Java 应用程序时执行 SwingUtilities.invokeLater 以确保 Swing 组件位于事件调度线程 (EDT) 上。
  2. 从 EDT 调用长时间运行的进程作为可运行线程。
  3. 在可运行线程中,由于您不在 EDT 上,因此在更新 Swing 组件时执行 SwingUtilities.invokeLater。这可确保 Swing 组件在 EDT 上更新。

每个 Swing 应用程序都应该以这样的类开始:

import javax.swing.SwingUtilities;

import com.ggl.text.entry.model.TextEntryModel;
import com.ggl.text.entry.view.TextEntryFrame;

public class TextEntry implements Runnable {

    @Override
    public void run() {
        new TextEntryFrame(new TextEntryModel());
    }

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

}

这个类做了 3 件事。

  1. 构造 GUI 数据模型。
  2. 构造 GUI JFrame。
  3. 确保 Swing 组件位于 EDT 上。
于 2013-04-29T14:29:43.287 回答
1

您还需要在 EDT 上调用更新。我建议在主线程上睡觉,让 GUI 有机会在任何其他工作之前出现:

someMethod() {
    // prevent GUI from freezing using threads
    Runnable r = new Runnable() {
        public void run() {
            status = new StatusFrame();
        }
    };
    SwingUtilities.invokeLater(r);
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
    }

//do something
    r = new Runnable() {
    public void run() {
            status.update("process 1 completed");
        }
    };
    SwingUtilities.invokeLater(r);


//do something else
 r = new Runnable() {
    public void run() {
            status.update("Process 2 completed");
        }
    };
    SwingUtilities.invokeLater(r);
}
于 2013-04-29T14:34:09.390 回答
1

请参阅Swing 中的并发

您可能会发现使用 Swing Worker 更容易使用,因为它使用 Thread 并且具有允许您正确更新 GUI 的方法。

于 2013-04-29T14:43:14.210 回答