我知道应该使用 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);
}
但是,当我运行这段代码时,我只看到菜单窗口。当我退出菜单时,当模拟窗口应该显示时——程序似乎已经关闭。
知道我在这里做错了什么吗?
最佳答案
尽管我不完全理解您的意图,但我可以毫无疑问地说您的做法是错误的。您的 while (true)
循环不应该存在,不应该存在于事件驱动的系统中,并且不符合事件驱动编程的概念。相反,您的代码应该由于对事件的 react 而改变状态,而不是这个永无止境的 while 循环。
另请注意,您编写的代码存在在创建之前调用模拟方法的风险。请注意,它是在调用 Run 方法(应命名为 run)的不同线程中创建的,并且您无法保证执行顺序,实际上可能会发生错误顺序,因为调用 Runnable 会有延迟代码,因为它首先必须在调用之前排队到事件线程。
为了获得更好的帮助,请考虑创建并发布 minimal, compilable, runnable program这向我们表明了您的问题。
编辑 1
此外,您还需要学习和使用 Java 命名约定,包括以大写字母开头的类名以及以小写字母开头的方法和变量名。
编辑 2 你声明:
Though essentially once this instantiation is done - all the program will do is update itself without any interaction. That was the idea of the loop. The loop will update the simulation, and in turn update what is being displayed.
如果您正在尝试运行 Swing 模拟,那么为什么不简单地使用 Swing Timer你的动画循环?您的代码几乎肯定会导致 Swing 线程故障。
编辑 3
在第 3 次或第 4 次阅读时,在我看来,您正在尝试从主应用程序以模式方式显示菜单 View ——也就是说,当菜单处于 Activity 状态时,主应用程序不可交互或不可见。如果是这样,请考虑 1) 为您的菜单窗口使用模态 JDialog。这样您就可以启动窗口,并且启动代码将在该位置停止,直到菜单窗口不再可见。然后您可以显示您的动画窗口。或者 2) 使用 CardLayout 交换 View 。这里有一个最初显示菜单 JPanel 的 JFrame 应用程序。然后,在处理完菜单后,您可以让 CardLayout 交换 View ,这样现在动画就会显示在它的位置上。
关于Java Swing 线程安全和 EDT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22080030/