Java Swing线程安全和EDT

时间:2014-02-27 20:48:34

标签: java swing jframe event-dispatch-thread invokelater

我知道应该使用invokeLater在事件调度线程(EDT)上安全地创建JFrame,并且我试图在我的main方法中创建其中两个。

代码:

public void run() {     

    // Handle Menu When Open
    menu.setVisible(true);
    while(menu.isVisible())
    {
        if(menu.isShowing() == false) {
            showMenu = false;
            showSimulation = true;
        }
    }
    menu.setVisible(false);

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            int[] dims = menu.SizeSetting();
            simulation = new Simulation(dims[0], dims[1]);
        }
    });

    simulation.run();
}

因此,菜单已创建(这似乎工作正常,因为此处所需的处理非常少)。在此之后,使用菜单,在menu.setVisible(false)处单击按钮被调用。之后,我在EDT上排队一个方法,Simulation是一个派生自JFrame的类。它的构造函数如下:

public Simulation(int width, int height) {
    this.setVisible(false);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("Traffic Light System - Simulation");
    grid = new Grid(0, 0);
    ready = false;

    grid = new Grid(width, height);
    addComponentsToPane(); // Set up visualization of grid here

    // Introduce cars here? e.g. grid.Get(0, 0).addCars(new Car[])?

    ready = true;
    setVisible(true);
}

addComponentsToPane()方法将所有必要内容添加到JFrame。在此构造函数之后调用的run()方法只是:

public void Run() { 
    while(isVisible()) {
        OneStep();
    }
    setVisible(false);
}

但是,当我运行此代码时,我只看到菜单窗口。当我退出菜单,并且应该显示模拟窗口时 - 程序似乎已关闭。

我在这里做错了什么想法?

1 个答案:

答案 0 :(得分:6)

即使我不完全明白你想要做什么,但我可以毫无疑问地说你错了。您的while (true)循环不应该存在,不应该存在于事件驱动的系统中,并且相信事件驱动编程的概念。相反,您的代码应该由于对事件的反应而改变状态,而不是在循环时永远不会结束。

另请注意,您的代码可能会在创建之前调用模拟方法。请注意,它是在调用Run方法(应该命名为run)的不同线程中创建的,并且您无法保证执行顺序,并且实际上可能发生了错误的顺序,因为调用Runnable会有延迟代码,因为它首先必须在被调用之前排队到事件线程。

为了更好的帮助,请考虑创建并发布一个minimal, compilable, runnable program,向我们展示您的问题。


编辑1
此外,您还需要学习和使用Java命名约定,包括以大写字母开头的类名以及以小写字母开头的方法和变量名。


编辑2 你说:

  

虽然基本上这个实例化完成后 - 所有程序都会自行更新而不进行任何交互。这就是循环的想法。循环将更新模拟,然后更新正在显示的内容。

如果您正在尝试运行Swing模拟,那么为什么不简单地使用Swing Timer进行动画循环?您的代码几乎可以保证导致Swing线程发生错误。


编辑3
在第3或第4次阅读时,在我看来,您正试图从主应用程序以模式方式显示菜单视图 - 即当菜单处于活动状态时,主应用程序无法交互或不可见。如果是这样,请考虑,1)在菜单窗口中使用模态JDialog。这样您就可以启动窗口,启动代码将在此位置暂停,直到菜单窗口不再可见。然后,您可以显示动画窗口。或者2)使用CardLayout交换视图。这里有一个JFrame应用程序,最初显示您的菜单JPanel。然后,当处理完菜单后,您将拥有CardLayout交换视图,以便现在动画显示在其位置。