3

我知道应该使用 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);
}

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

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

4

1 回答 1

6

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

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

为了获得更好的帮助,请考虑创建和发布一个最小的、可编译的、可运行的程序,向我们展示您的问题。


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


编辑 2 你说:

虽然基本上一旦这个实例化完成 - 程序所做的就是在没有任何交互的情况下更新自己。这就是循环的想法。循环将更新模拟,进而更新正在显示的内容。

如果您正在尝试运行 Swing 模拟,那么为什么不简单地将Swing Timer用于动画循环呢?您的代码几乎肯定会导致 Swing 线程故障。


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

于 2014-02-27T20:55:07.977 回答