JFrame + Canvas:为什么在调用glViewport时会出现NUllPointerException?

时间:2011-03-10 22:27:16

标签: java swing opengl awt lwjgl

我已经在其中创建了一个带有画布的JFrame,就像您在下面的代码中看到的那样。我想要做的是在屏幕大小更新时调整openGL上下文大小。这应该像调用glViewport()一样简单,我在名为resize()的事件处理程序中执行此操作。然而,这导致了这个:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at org.lwjgl.opengl.GL11.glViewport(GL11.java:3199)
at gltest.GameMain.resize(GameMain.java:149)
at gltest.GameMain$1.componentResized(GameMain.java:59)
(...)

我完全无能为力。从画布大小返回的边界似乎没有问题,但是一旦我在视口上使用它们,它们就会抛出错误。当我改为将视口调用为“glViewport(1,1,100,100)”时,也会发生同样的情况。所有这些值都在窗口的边界内,但是当我调整窗口大小时它仍会抛出相同的nullPointerExceptions。

我没有想法和能量来弄清楚为什么(我现在谷歌搜索3小时,没有结果)。我做错了什么?

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;

import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import static org.lwjgl.util.glu.GLU.*;
import static org.lwjgl.opengl.GL11.*;

public class GameMain {
    public JFrame frame;
    public Canvas canvas;

    public boolean initialize(int width, int height) {
        try {
            Canvas canvas = new Canvas();
            JFrame frame = new JFrame("Open Rock Raiders - Delta");
            this.canvas = canvas;
            this.frame = frame;
            ComponentAdapter adapter = new ComponentAdapter() {
                public void componentResized(ComponentEvent e) {
                    resize();
                }
            };

            canvas.addComponentListener(adapter);
            canvas.setIgnoreRepaint(true);
            frame.setSize(640, 480);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(canvas);
            frame.setVisible(true);
            Dimension dim = this.canvas.getSize();

            Display.setLocation(100, 100);
            Display.setTitle("GL Window");
            Display.setDisplayMode(new DisplayMode(dim.width, dim.height));
            Display.setParent(canvas);
            Display.create();

            //openGL setup
            glViewport(0, 0, dim.width, dim.height);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            gluPerspective(60.0f, (float)(dim.width/dim.height), 0.1f, 10000.0f);
            glMatrixMode(GL_MODELVIEW);
            glClearColor(94.0f/255.0f, 161.0f/255.0f, 255.0f/255.0f, 0.5f);
            glClearDepth(1.0);
            glShadeModel(GL_FLAT);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glEnable(GL11.GL_CULL_FACE); 
            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        } catch (LWJGLException le) {
            le.printStackTrace();
        }
        return false;
    }

    public void resize()
    {
        Dimension dim = this.canvas.getSize();
        GL11.glViewport(0, 0, dim.width, dim.height);
    }
}

2 个答案:

答案 0 :(得分:1)

您应该从主线程执行所有显示操作。如果您查看在其他问题中发布的示例,您可以看到新的画布大小已存储,然后由主线程更新。它也是线程安全的。你需要这样做,然后在你的图形初始化之后有一个循环:

while (!closeRequested) {
    GL11.glViewport(0, 0, dim.width, dim.height);
    Display.update();
}

//finished
Display.destroy();

答案 1 :(得分:0)

很可能你在opengl初始化之前得到了第一个resize事件。在OpenGL设置之后移动canvas.addComponentListener(adapter);