Java Swing 线程安全和 EDT

标签 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);
}

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

知道我在这里做错了什么吗?

最佳答案

尽管我不完全理解您的意图,但我可以毫无疑问地说您的做法是错误的。您的 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/

相关文章:

java - 图形元素不会出现在 JFrame (Java) 中

Java,如何重置 JTextField

Java JInternalFrame 到 JPanel

java - 使用 log4j 进行 Spring Boot 日志记录 - 如何启用 Spring Boot 日志条目?

java - 需要 Spring 事务的帮助来进行巨大的日期操作

java - 如何关闭 eclipse 中某些文件夹(如 node_modules)的 javascript 验证(包括 tern/lint/jshint)?

java - Collection的reverseOrder方法的时间复杂度

java - 设置用作 JTable RowFilter 时 JComboBox 中显示的选项数量

java - 使用 JTable+focusLost() 错误显示数据

java - 将 JFrame 插入 Swing 中的选项卡