In Canvas mode, the initial Camera sizes are set up as width and height as found in the Settings object, but when Swing’s LayoutManager resizes the Canvas, the cameras get resized to the actual pixel size of the Canvas.
Ideally, the Camera would simply query the Lwjgl display about actual width and height and use that, but I don’t know whether this is reliable enough in fullscreen mode, or whether the display can actually be queried about width and height already. I don’t have fullscreen or Android deployment here, so I can’t properly test any fix.
So I’m forced to leave the fix to those who know JME3 better than me 
For now, my workaround is this:
[java] @Override
public void initialize() {
super.initialize();
NiftyJmeDisplay display = new NiftyJmeDisplay(assetManager, inputManager,
audioRenderer, viewPort);
// Bug workaround: JME initializes the display for width and height
// as found in the Settings, not as computed by Swing’s layout.
// This call rectifies things (but causes flicker).
display.reshape(
viewPort,
viewPort.getCamera().getWidth(),
viewPort.getCamera().getHeight());
guiViewPort.addProcessor(display);
…
}
[/java]
This is more a display of what doesn’t work than an actual solution:
- It ignores the scene graph. I can’t easily verify whether the scene graph is sized correctly because I currently have no landmarks that I can watch.
- The first frame is still rendered with the wrong size, frames 2 and onwards are rendered with the Canvas size. This causes initial flicker, which is a bad first impression on anybody using the game.
I’m still showing it so people can do better
Well, the above worked initially, but as soon as I touched some not-quite-right issues elsewhere in the application start-up code, it broke again.
I have been unable to determine what exactly the problem is. There seem to be multiple code paths that lead to different kinds of misbehaviour:
- Pick up width and height from AppSettings.
- Pick up width and height from a 0x0 parent component. I got a “value out of range” error when it tried to create the in X Windows.
- Pick up width and height from an invalid (i.e. layout-pending) parent component.
The latter two originate from within LWJGL 2.8.4, the former is JME from a week ago. I don’t know what would be the best way to address this.
What currently works for me is this:
- Set up the Swing GUI inside Application#start().
- Make the GUI visible (UPDATE: and call validate() on it). This forces Swing to layout everything, including the parent of the canvas.
- Use SwingUtilities.invokeLater() to run this code:[java] createCanvas();
JmeCanvasContext context = (JmeCanvasContext) getContext();
frame.add(context.getCanvas());
frame.validate();[/java]
This will flash the background color in the canvas area until the canvas starts. That’s roughly 3 seconds (plus another 3 seconds until Nifty is done initializing).
Well, better have two 3-second waits than a single 6-second one.
Important: Putting step 2 inside a SwingUtilities.invokeLater() created a race condition and would occasionally make the Lwjgl canvas try to create a 0x0 window again.
Important #2: You will get multithreading as soon as step 2 starts. Make sure that any data that the AWT event loop (i.e. Swing) OR the LWJGL render loop need are already set up, or use synchronized access.
It’s all too easy to get that wrong. The main program should not try to do anything clever after that setVisible(true) call.
@admin This has grown into a mixture of troubleshooting and bug reporting, I’m not sure whether this belongs into this subforum anymore. Please feel free to adjust as appropriate.
1 Like