简体   繁体   中英

JFrame + Canvas: why do I get a NUllPointerException when calling glViewport?

I have created a JFrame with a canvas in it, like you can see in the code below. What I am trying to do is to make the openGL context resize when the size of the screen gets updated. This should be as easy as a call to glViewport(), which I am doing in the event handler called resize(). That, however, results in this:

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)
(...)

I am completely clueless. The boundaries returned from the size of the canvas seem to be allright, but once I use them on the viewport, they throw errors. The same happens when I instead make the viewport call like "glViewport(1, 1, 100, 100)". All these values are well within the boundaries of the window, yet still it throws the very same nullPointerExceptions when I resize the window.

I am out of ideas and energy to figure out why (I have been googling for 3 hours now, no result). What am I doing wrong?

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);
    }
}

You should do all of the display operations from the main thread. If you look at the example you posted in your other question, you can see the new canvas size is stored and then updated by the main thread. It's done thread-safely too. You need to do that and then have a loop after your graphics initialisation something like this:

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

//finished
Display.destroy();

Most likely you're getting the first resize event before opengl gets initialized. Move canvas.addComponentListener(adapter); after the OpenGL setup stuff.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM