3

我读过几本关于Java的书。在他们所有人中至少有一章讲授GUI编程。在所有这些,创建一个简单的表格申请按照这样的逻辑:应该从Event Dispatcher或主线程控制Swing GUI应用程序吗?

MyFrame.java

public class MyFrame extends JFrame 
{ 
    JButton button1; 

    public MyFrame() 
    { 
     button1 = new JButton("Click here."); 
    } 
} 

FrameTest.java:

public class FrameTest 
{ 
    public static void main(String[] args) 
    { 
     MyFrame myFrame = new MyFrame(); 

     myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     myFrame.setSize(600, 600); 
     myFrame.setVisible(true); 
    } 
} 

基本上,只要子类JFrame的创建形式和将其他组件声明为实例变量并在构造函数中初始化这些组件。然后创建另一个测试类,在该类中实例化框架子类并调用其某些方法以使其可见。

但是在并发课程中,我了解到我们有一个主线程,它在我们创建的每个应用程序中运行main()。据我所知,当我们使用Swing来创建GUI应用程序时,我们有另一个线程(Event Dispatcher Thread)。所以如果我没有弄错,在每个基于Swing的GUI应用程序中至少有两个线程。这使得每个GUI应用程序都是多线程的。在我读过的一些文章和教程中,它指出Swing不支持多线程,因此所有GUI组件都应该仅在Event Dispatcher Thread中创建和修改,否则可能会出现线程干扰和内存不一致错误。

即使在维基百科(http://en.wikipedia.org/wiki/Swing_%28Java%29)的最简单示例中,它也是通过invokeLater方法制作的。

那么哪一个才是真正的方法?我错在哪里?

+3

无论是否扩展'JFrame',关键是要在'EDT'上执行GUI任务。所有耗时或阻塞的活动(如网络I/O)都应该在单独的线程中运行(例如,通过'SwingWorker'委托)以避免GUI冻结。 – asgs 2013-03-13 20:17:20

回答

7

与任何UI/Swing组件交互必须在美国东部时间范围内完成

当启动一个应用程序,你应该确保你在美国东部时间内,然后再尝试和创建/任何交互执行Swing组件。

简单地说,你应该使用类似...

EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     // Now in the event dispatching thread 
    } 
}); 

如果你需要运行长时间运行的任务或执行任何任务阻塞,你应该在一个单独的线程中执行它。在大多数情况下,SwingWorker是一个不错的选择,因为它提供了一些简单的机制来将代码重新同步到事件分派线程。

取读通过

所以,简单的答案是肯定的,所有基于Swing代码应访问/修改/从的情况下与之交互EDT

3

所以如果我没有弄错,在每个基于Swing的GUI应用程序中那里 至少有两个线程

是的。一个是主线程,另一个是EDT(Event Dispatch Thread)。

这使得每个GUI应用程序都是多线程的。

是的。但在这种情况下,另一个线程不会与GUI组件交互。

摇摆不支持多线程,因此所有的GUI组件 只应在事件调度线程 创建和修改,否则螺纹干涉和内存不一致的错误可能出现 。

是的,绝对正确。这意味着一次只有一个线程应该与给定的GUI组件交互。
与下列种的线程的摆动程序员特价:

  • Initial threads,即执行初始应用程序代码的线程。
  • event dispatch thread,其中执行所有事件处理代码。与Swing框架交互的大多数代码也必须在此线程上执行。
  • Worker threads,也被称为后台线程,执行耗时的后台任务。

程序员并不需要提供明确创建 这些线程代码:它们是由运行时或摇摆 框架提供。程序员的工作是利用这些线程来创建一个响应式,可维护的Swing程序 。

相关问题