Problems with Swing/AWT, how to convert GLCanvas to GLJPanel?

Hey

Im currently working on a game project (a turnbased multiplayer tactical strategy game :slight_smile: ). The idea was to handle menus using Swing and then start the game. The game would be run on a different JFrame, using a class that extends Canvas. Render calls are made from inside the gameloop. Both the menus and the game work as they are supposed to separetly, but when trying to start the game from a call in the menus thereā€™s a problem. I surmize its from the heavyweight/lightweight issue.

The JFrame that houses the GameCanvas ( extended from a Canvas in the same way as in http://fivedots.coe.psu.ac.th/~ad/jg/jogl1/index.html, active rendering ) doesnt seem to get focus when calling the canvas.requestFocusInWindow() method. No events are passed to the listeners that have been added to the JFrame or the GameCanvas on it. The method is called after a ā€œLaunch gameā€ button is pressed, but the button seems to keep focus. I also tried to change the button to .setFocusable(false), but then focus was just given to another Swing component (a JTextfield).

I thought I could fix this by changing the code so that GameCanvas extends JPanel instead of Canvas, but this causes the following exception:
Exception in thread ā€œmainā€ javax.media.opengl.GLException: Unable to lock surface
at com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.lockSurface(WindowsOnscreenGLDrawable.java:170)
at com.sun.opengl.impl.windows.WindowsOnscreenGLContext.makeCurrentImpl(WindowsOnscreenGLContext.java:57)
at com.sun.opengl.impl.GLContextImpl.makeCurrent(GLContextImpl.java:134)
at top.game.renderer.GameCanvas.makeContentCurrent(GameCanvas.java:457)
This is not the case when extended from Canvas.

So, what would be the best way to fix this? Can i fix the code so that the hw component gets focus, or is there a way to extend a JPanel to use with JOGL (similar to the extend Canvas solution, but for GLJPanel)?

The code of the constructor


public class GameCanvas extends Canvas {
    ...
public GameCanvas(GameWindow top, int width, int height,
                         GraphicsConfiguration config, GLCapabilities caps,
                         SpriteFactory store, SpriteBuffer sBuffer, PickingBuffer pBuffer,
                         Engine2RendererInterface engine){ 
        super(config);
    	
        // the usual attributes for a canvas
        this.top = top;
        panelWidth = width;
        panelHeight = height;

        // get a rendering surface and a context for this canvas
        drawable = GLDrawableFactory.getFactory().getGLDrawable(this, caps, null);
        context = drawable.createContext(null);
        
        sStore = store;
        this.sBuffer = sBuffer;
        this.pBuffer = pBuffer;
        this.engine = engine;  
        
        inSelectionMode = false;
        xCursor = 0;
        yCursor = 0;
        
        this.character = null;
        this.tile = null;
    }

The ā€˜modulesā€™ are not yet fully functional, but i posted them on my page so you could run them.
http://www.cs.tut.fi/~vuori7/Applications/BLGUI/blgui_demo.jnlp
http://www.cs.tut.fi/~vuori7/Applications/BLGAME/blgame_demo.jnlp

The gui launches the whole app, and if you click ā€œhostā€, ā€œlaunch defaultā€, ā€œlaunchā€, it should start the game with one player. But the gamewindow just hangs there.
The game uses a Tester class as the main class, wich populates the game. It runs as itā€™s supposed to.

The program asks for access to the computer, for writing a ā€œ.BloodLetters/config.xmlā€ file into the users home directory. I can disable this if you do not wish to give it permission.

Any help will be greatly appriciated. If you require any additional information ill be glad to supply it.

ā€“Mika Vuoriā€“

Iā€™m no expert on AWT / Swing focus issues but have you called setFocusable(true) on your GameCanvas and if not does that change the behavior?

Yes, I have set the canvas focusable. In the init method of the renderer I put this to see if it would change the behavior.


public void init( Dimension resolution, boolean effects, boolean fullScreen ){
		camera.initCameraPosition();
		window.init(camera, resolution, chat);
		window.initRender();
		window.setFocusable(true);
		window.getCanvas().setFocusable(true);
		
		if(window.getCanvas().requestFocusInWindow()){
			System.out.println("Canvas getting focus");
		}else{
			System.out.println("Canvas cant get focus");
		}
	}

It does say that canvas should get focus, yet it doesnt. It does not change the behavior.

This propably wouldnt be a problem if the component was lightweight. Any suggestion on how to go about changing the canvas class, or is it even possible to have it as lightweight?

Try to simplify things to figure out exactly whatā€™s going on. Replace your GameCanvas with a regular Canvas or a GLCanvas and see whether the behavior is different.

You are not going to be able to create a GLDrawable for a JPanel. If you need a lightweight component you will need to either use JOGLā€™s GLJPanel or implement something similar to it.

If you can boil things down into a simple and self-contained test case we can look at it further.

Note that several of the JOGL demos combine Swing widgets or menus with a heavyweight GLCanvas and focus transfers seem to work fine.

[quote]Try to simplify things to figure out exactly whatā€™s going on.
[/quote]
Thanks for this :). I seem to have a habit of assuming things, especially when coding long times without taking breaks. feels like such a noob

Now that I looked at the code again I notice that I call startGame() (starts the game loop) from the ActionListener that listens to the ā€œlaunch gameā€ button. A big no-no :P. Just focusing the canvas works fine.

Now to just change it so that it invokes another Thread to start the gameā€¦

Thanks for your help!