【问题标题】:Java Swing GUI Freezing When Calling Method [duplicate]调用方法时Java Swing GUI冻结[重复]
【发布时间】:2015-03-06 09:16:10
【问题描述】:

我对 Swing 很陌生,但对 Java 不是。无论如何,我有一个国际象棋程序。这是游戏循环类中重要的部分:

public class game {
    static Board gameboard = new Board();
    public static boolean waitstatus = true;
    public static char currentfaction = 'w';
    public static boolean done = false;
    public static boolean resigned = false;
    public static boolean wplayern = false;
    public static boolean bplayern = false;
    public static gui boardwindow = new gui();

    public static void main(String[] args) {
        gameboard.init(8, 8);
        gui.startGUI(boardwindow);
        runner();
        while (true) {
            //spin
        }

    }

    public static void runner() {
        done = false;
        resigned = false;
        wplayern = false;
        bplayern = false;
        boolean stalemate = false;

        while (true) {
            //The loop stuff    
        }
    }

    public static void resetGame() {
        if (!done) {
            System.out.println("Game's not finished yet!");
        } else {
            gameboard.restart();
            waitstatus = true;
            currentfaction = 'w';
            done = false;
            resigned = false;
            wplayern = false;
            bplayern = false;
            boardwindow.redraw();
            rerun();
        }
    }

    public static void rerun() {
        runner();
    }
}

这就是有问题的代码。顺便说一句,boardwindow 是一个 gui 对象,gameboard 是我的内部逻辑游戏板数组,redraw() 具有 gui 重绘(更新棋子的位置),restart() 将内部逻辑板重新启动到原始开始游戏状态。 gui 类是一个swing gui,非常简单,而且效果很好。问题是,在游戏循环中,当它被将死时,循环中断并且 runner() 函数结束。然后,用户应该能够在 gui 中按下新游戏按钮,以在将死后重新启动游戏。新的游戏按钮调用 resetGame()。问题是再次调用 runner() 时 gui 窗口会冻结,我不知道为什么,我想它不需要多个线程。我还有其他按钮可以调用我没有向您展示的函数,这些函数会调用其他函数,例如 restart() 等,它们没有问题,只有在调用 runner() 时才会出现问题。

我知道我的其他代码在格式和约定方面可能很糟糕,但请尽量将答案集中在主要问题上。

谢谢

【问题讨论】:

  • 您是否注意到控制台日志中有任何错误?
  • 我不确定你的情况,但 Java Swing 中冻结 GUI 的几乎所有问题都与使用 EDT 的错误有关:docs.oracle.com/javase/tutorial/uiswing/concurrency/…
  • 不要依赖static,它不是跨对象通信机制,会炸你的脸
  • 控制台日志中没有错误,我意识到 Swing 中 GUI 冻结的大多数问题都来自线程处理不当,但我的问题与我见过的大多数其他示例不同。此时我并不想同时运行两种方法,即使在其他情况下,当我同时运行两种方法时,GUI 也能很好地处理它。我使用静态是因为我不想为游戏创建单独的对象,因为它确实不需要单独的对象。
  • 不要阻塞 EDT(事件调度线程)。发生这种情况时,GUI 将“冻结”。有关详细信息和修复,请参阅 Concurrency in Swing

标签: java swing user-interface event-dispatch-thread


【解决方案1】:

您应该设置一个条件来控制循环,而不是将其设置为 true。即使在从 resetGame() 重置游戏后,循环也会继续运行;或使用中断;

public static void runner() {
    done = false;
    resigned = false;
    wplayern = false;
    bplayern = false;
    boolean stalemate = false;

    while (true) {
        //The loop stuff 
        if(newGameClicked == true){//just to literally make meaning
            break;
        }
    }
}

或者作为一个快速修复,您可以简单地调用 boardwindow.dispose();然后创建一个新的 gui() 实例并将其设置为 visible() 以在单击新游戏按钮时重新启动游戏

【讨论】:

  • 哪个while循环,在runner还是main?
  • 在亚军中。或者更好的是看到 How do I use SwingWorker in Java? 了解如何使用摇摆工人来做这样的事情
  • 那么我是否可以让我的游戏类成为一个摇摆工人,然后让我的 runner () 作为后台执行,并由新游戏按钮执行?听起来对吗?我还能像现在一样拥有可以从 gui 调用的所有其他辅助函数吗?
  • 是的。 runner() 方法应该在后台执行,因为它处理在后台运行的循环。您的其他辅助函数会更新变量,因此它们不必存在,除非那些直接更新您的 gui。与您当前在 runner() 方法中的内容一样,在此处使用条件。查看我更新的答案
  • 哦,你没看到吗,在 while 循环中,当它被将死时我确实会中断。这几乎是 if(checkmate) break;并且 resetGame() 只会在 runner() 函数结束后运行。那我还应该使用后台运行吗?
猜你喜欢
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 2013-11-05
  • 1970-01-01
  • 2021-11-09
相关资源
最近更新 更多