为什么我的Canvas在添加到JFrame后无法绘制?

时间:2011-11-19 09:03:10

标签: java swing lwjgl

我正在编写一个使用Canvas实例绘制的小游戏(如果它很熟悉;我使用游戏库LWJGL)。 现在我已经为我的游戏创建了一个主菜单,其中包含一个JPanel,然后我在游戏开始时将其添加到我的主游戏JFrame中;

Canvas canvas = new Canvas();
JFrame frame = new JFrame("Puzzler");
this.canvas = canvas;
this.jframe = frame;
canvas.setIgnoreRepaint(true);
frame.setSize(640, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

接下来,我创建主菜单:

this.mainMenuPanel = new MainMenuPanel(this.main);
this.jframe.setSize(500, 170);
this.jframe.getContentPane().add(mainMenuPanel);
this.jframe.validate();

最后,当主菜单想要启动游戏时,我尝试用Canvas实例替换主菜单的JPanel:

this.jframe.setVisible(false);
this.jframe.invalidate();
this.jframe.removeAll();
this.jframe.getContentPane().add(canvas);
this.jframe.setVisible(true);
this.jframe.pack();
this.jframe.setSize(640, 480);
this.jframe.validate();

当最后一段代码运行时,对LWJGL的Display.create()的调用会返回Canvas不可绘制的错误。 我已经尝试了一大堆组合(比如添加JPanel作为Canvas的容器,没有运气),并且一直在搞乱validate()和repaint()调用的命令,因为它有时会有助于摆动。有谁知道这里可能出现什么问题?

修改 我已经解决了这个问题。问题结果是java的事件处理线程在运行主循环时遇到困难,因为我在主线程而不是start()上调用了run()。傻我。 :P

2 个答案:

答案 0 :(得分:3)

不要混合swing和awt组件。帆布是awt。使用JPanel覆盖paintComponent Graphics g)方法。

http://java.sun.com/products/jfc/tsc/articles/mixing/

http://www.devx.com/tips/Tip/14718

答案 1 :(得分:3)

除了非混合规则之外,我的猜测是你会在纯粹的awt上下文中得到类似的异常 - 来自LWJGL tutorial Basic applet

  

现在我们已经拥有了基本模板,我们需要坚持LWJGL原生   显示在上面。为此,我们只需使用Display.setParent(Canvas)   方法。但是,在我们创建显示之前,我们需要确保   画布已准备就绪。为了确保这一点,我们将使用   awt画布的addNotify()方法告诉我们画布的时间   准备就绪,我们可以创建显示。同样我们将使用   removeNotify()通知我们画布即将被销毁   我们应该清理并关闭原生显示器。

修改

(仍然没有IDE,只是从我的头顶; - )

实际上,我不太明白你对removeXX做了什么,不希望有任何需要。首先,我会保持简单,完全如教程中所示:

 display_parent = new Canvas() {
    public final void addNotify() {
       super.addNotify();
       startLWJGL();
    }
    public final void removeNotify() {
      stopLWJGL();
      super.removeNotify();
    }
 };
 frame.add(display.parent);

另外确保所有更改都发生在EDT上 - 这可能是真正的问题,不知道Display在这些方法中实际做了什么:

 public void gameLoop() {
     while(running) {
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                 Display.sync(60);
                 Display.update();
             }
         });
    }

    Display.destroy();
 }      

修改2

只需在JFrame中运行示例(在上面引用的教程中),不对现有代码进行更改,只需添加一个main:

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Gears AWT");

        final JPanel intro = new JPanel();
        Action action = new AbstractAction("Start Gears") {

            @Override
            public void actionPerformed(ActionEvent e) {
                GearsApplet gears = new GearsApplet();
                gears.init();
                frame.remove(intro);
                frame.add(gears);
                frame.getRootPane().revalidate();
            }
        };
        JButton button = new JButton(action);
        intro.add(button);
        frame.add(intro); //.display_parent);
        frame.setSize(200, 200);
        frame.setVisible(true);
    }

感觉还不错(在第一次近似中,怀疑有一些魔鬼隐藏在穿线的较暗处 - 因为我们在EDT上(最有可能)),齿轮正在运行且组是可以旋转的