从其他类调用时不加载JFrame

时间:2016-04-01 18:09:36

标签: java swing

基本上我有一个主要类的游戏。

    public static void main(String[] args) throws InterruptedException {
    JFrame frame = new JFrame("Mini Tennis");
    Game game = new Game();
    frame.add(game);
    frame.setSize(300, 400);
    frame.setResizable(false);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    while (true) {
        game.move();
        game.repaint();
        Thread.sleep(10);
    }
}

当我直接加载一个类时,它工作正常。

enter image description here

但是当我从另一个类调用它时,它不会绘制任何东西。

    private void btnGameActionPerformed(java.awt.event.ActionEvent evt) {                                        
  try {
      String[] args = null;
      Game.main(args);
    } catch (InterruptedException ex) {
        Logger.getLogger(DrawerMain.class.getName()).log(Level.SEVERE, null, ex);
    }

}  

enter image description here

几秒钟后,它描绘了我输了一场比赛。所以基本上游戏正在运行,但我什么也做不了,我什么也没看到。

enter image description here

4 个答案:

答案 0 :(得分:1)

原因是在第二种情况下,您从ActionListener调用main方法,您在UI线程上运行main方法。由于您在此代码中拥有活动的等待块,因此UI永远无法绘制任何内容。您应该查看javax.swing.Timer并使用Timer的实现替换我在下面复制的循环

while (true) {
        game.move();
        game.repaint();
        Thread.sleep(10);
    }

答案 1 :(得分:0)

首先,您不应该从主线程运行所有内容。并且main方法不适合您调用,它应该是您应用程序的入口点。

在您的主要方法中,执行以下操作:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createAndShowGUI(); // in this method, you create your frame and other UI components and show them
    }
});

Runnable将在事件派发线程中运行,并且会在与UI相关的任何操作之前准备好UI。

一旦准备好UI,就可以创建框架并将其链接到游戏中。然后使用一个类似于框架和游戏的控制器的类来收听它感兴趣的事件,并在需要时更新UI。

如果每次发生某些事件时都需要创建一个运行此游戏的窗口,那么您应该将此窗口定义为一个类。您只需要创建此类的实例并使窗口可见。或者,如果您只需要重新启动游戏,则在整个应用程序中使用该类的单个实例,并仅在其中重新启动游戏。控制器类始终可用于通知游戏重新启动以及更新UI。

答案 2 :(得分:0)

您需要将main代码移动到构造函数中,main应仅在第1类或" main"你打算上课。

main method是您运行应用程序的入口点,您不应该像使用其他任何方法一样调用它。

public Game () {
    JFrame frame = new JFrame("Mini Tennis");
    Game game = new Game();
    frame.add(game);
    frame.setSize(300, 400);
    frame.setResizable(false);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    while (true) {
        game.move();
        game.repaint();
        Thread.sleep(10);
    }
}

然后你把它称为:

private void btnGameActionPerformed(java.awt.event.ActionEvent evt) {                                        
  try {
      String[] args = null;
      Game game = new Game();
    } catch (InterruptedException ex) {
        Logger.getLogger(DrawerMain.class.getName()).log(Level.SEVERE, null, ex);
    }

}  

您应该详细了解ConstructorsClasses and Objects

同样如其他答案中所述,Thread.sleep()会导致您的应用程序冻结,您应该使用Swing Timer代替在另一个线程中处理它,这样您的应用程序就不会冻结。

使用Thread.sleep(),您的应用程序将在重新绘制之前等待其中的时间。

答案 3 :(得分:0)

Asothers说过,你不应该自己打电话给main()。也就是说,你的循环中不能有一个Thread.sleep() - 如果它在EventDispatchThread(它必须是)上运行,它将阻塞该线程并且你永远不会重新获得重绘。您需要使用SwingWorker进行循环。