Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing JFrame为游戏启动另一个JFrame_Java_Swing_Event Dispatch Thread - Fatal编程技术网

Java Swing JFrame为游戏启动另一个JFrame

Java Swing JFrame为游戏启动另一个JFrame,java,swing,event-dispatch-thread,Java,Swing,Event Dispatch Thread,我正在用Java开发一个小游戏。我的应用程序有一个主JFrame,可以通过单击JButton创建另一个窗口(游戏窗口)。 我已经单独测试了我的游戏窗口,一切正常 这是我的游戏窗口构造器: public GameWindow(final GameController controller) { super("Boulder Dash Game"); this.controller = controller; this.controller.registerObserver

我正在用Java开发一个小游戏。我的应用程序有一个主JFrame,可以通过单击JButton创建另一个窗口(游戏窗口)。 我已经单独测试了我的游戏窗口,一切正常

这是我的游戏窗口构造器:

public GameWindow(final GameController controller)
{
    super("Boulder Dash Game");

    this.controller = controller;
    this.controller.registerObserver(getCurrentFrame()); 
    this.gamePanel = new GamePanel(controller);

    this.frameWidth = controller.getColumns() * 16;
    this.frameHeight = controller.getRows() * 16 + 76;

    getContentPane().add(gamePanel, BorderLayout.CENTER);

    setSize(frameWidth, frameHeight);
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    controller.startGame();
}
方法启动游戏循环。 当我直接从主窗口启动此窗口时,游戏循环工作正常

现在,我想从我的主框架启动这个游戏窗口框架。 以下是我的主框架中的代码:

playButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(final @Nullable ActionEvent e)
    {
        String selectedItem = (String) levelsComboBox.getSelectedItem();
        assert selectedItem != null;
        controller.lauchGame(selectedItem);
    }
});
controller.launchGame(String selectedItem)是一种用于加载游戏级别和启动游戏窗口的方法。 这是密码

public void lauchGame(final String levelQueried)
{
    assert levelQueried != null;
    Level level = LevelRepository.load(levelQueried);
    assert level != null;
    GameController controller = new GameController(model);
    GameWindow view = new GameWindow(controller);
}
我的问题是,当我从另一个JFrame启动GameWindow时,上面没有任何元素。如果我没有在构造器中启动游戏循环,我的游戏窗口似乎初始化正确(内容、关闭时退出…)。但是当我启动gameloop时,我只是有一个空的JFrame(大小正确),没有内容。。当我试图退出画面时,我不能

以下是我的游戏循环代码:

public void start() throws InterruptedException // Game loop method
{
    boolean updateGame = true;
    while ( !isFinish() ) {
        // We update the elements only 1 round of 2
        if ( updateGame ) {
            updateExitState();
            getPlayField().updateMoovableEntities();
            updateGame = false;
        } else {
            updateGame = true;
        }
        Thread.sleep(100);
        // Animate the sprite at every round
        setChanged(); 
        notifyObservers(); // inform that a repaint is necessary
    }
    LOGGER.debug("The game loop for the current level is now finished.");
}
在控制台上,我可以看到gameloop正在运行,并且正确地调用了update方法。。。但是paintComponent从未被称为。。。所以我的镜框上什么都没有

我对这个问题一无所知。。。有人能帮我吗

编辑:

谢谢你的回答。我已经使用

javax.swing.SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run()
    {
        controller.startGame();
    }
});

这是一个更好的一点,现在我的框架已正确初始化。但现在还有另一个问题,监听器不再可用。。。我根本无法与我的框架交互(无法退出或执行任何其他操作…)。怎么了?

通过在Swing事件线程(EDT或事件调度线程)上运行
while(true)
循环,您完全冻结了它。不要那样做。相反,在后台线程中运行while循环,或者使用Swing计时器驱动游戏循环。阅读更多关于此的信息。另外,请阅读本网站上的问题


请注意,当您(错误地)在main方法中启动GUI和游戏循环时,游戏循环在主线程中运行,而不是在Swing事件线程中运行,因此在这种情况下,游戏可以正常运行,但这不是一个好的解决方案,因为主GUI也从Swing事件线程启动,这可能会导致间歇性的难以调试的线程错误

通过在Swing事件线程(EDT或事件调度线程)上运行
while(true)
循环,您完全冻结了Swing事件线程。不要那样做。相反,在后台线程中运行while循环,或者使用Swing计时器驱动游戏循环。阅读更多关于此的信息。另外,请阅读本网站上的问题


请注意,当您(错误地)在main方法中启动GUI和游戏循环时,游戏循环在主线程中运行,而不是在Swing事件线程中运行,因此在这种情况下,游戏可以正常运行,但这不是一个好的解决方案,因为主GUI也从Swing事件线程启动,这可能会导致间歇性的难以调试的线程错误

你在EDT的上下文中启动游戏循环,这会阻止它,阻止它处理事件队列,包括绘制请求。当你单独运行它时,它工作的原因是因为类us在“main”循环中启动,这意味着你在EDT的上下文中启动了游戏循环,这会阻止它,阻止它处理事件队列,包括绘制请求。当您单独运行它时,它工作的原因是因为类us在“main”循环中启动,这意味着您侥幸成功。您可能会提到“main”循环和EDT之间的差异,以便op了解它为什么单独工作,这样可能会避免“但它在我这样做时工作…”注释:PYou可能会提到“main”循环和EDT之间的区别,以便op理解它为什么独立工作,这样可能会避免“但它在我这样做时工作…”注释:P