Light Problem when I use render/DisplaySystem in different Canvas


In my Swing application, I use different JPanels with a CardLayout to guide user in different steps. So when he go to next step, interface change. This is the main mechanism.

So I need to show the 3D view in different steps, but as there is only one 3D view, I must transfer it (in fact the Canvas) in each Panel.

So I use a basic panel.add(canvas3d) to change it.

When I create 3D view, all is ok, I can see my Duck like this

My problem is when I transfer the Canvas in a different Panel, my textures disappared and duck is black, like if renderer is not initialised. My duck looks like this :

To create Canvas I use :

display.createCanvas(width, height);

LightState seems to be broken
I supposed I must reset Renderer or DisplaySystem, or reinitialise them, but I try to call different functions but without change.

I call a function each time I change step, and I notice that renderer background is reset too. So I must to changeBackground each time. I use this :

Callable<?> call = new Callable<Runnable>() {
         public Runnable call() throws Exception {
            setBackgroundColor(ColorRGBA.white); // must to set background each time
            rootNode.updateGeometricState(0, true);
            DisplaySystem.updateStates(renderer); // nothing change
            return null;

So First do you know why Renderer (or something like this) is reset each time, just because I move tha Canvas ?

And do you know how to re initialise renderer or Display to get the initial state ?

Try this and see if it helps:

(  (JMECanvas) canvas ).setAutoKillGfxContext( false );

Ok, thank you very much, now display works (even if camera doesn't, but it's an other story :slight_smile: )

Unfortunatly, I use Jme1.0, and setAutoKillGfxContext is not implemented in LWJGLCanvas. I have seen you did a patch for Jme2.0, so I get code to try and it works, but it's just a test and I am not sure it's perfect, because there are more differences in Jme2.0 Canvas.

So please, can you do a patch for Jme1.0 to add this function, because it's not possible for me to migrate now to Jme2.0 (lot of works is already done) ?


Unfortunatly, jME 1.0 is pretty much 'frozen'; one of the old developers would have to make that change since only they had access to the old CVS…

(although IMO jME 2.0 is WAY better than 1.0, I also had to recently take a large cavas based 1.0 project to 2.0 and was surprised at how painless it actually was.  ;))

If it helps here is a bundled canvas and implementer class you can look at or use:

import com.jme.input.InputSystem;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.scene.Node;
import com.jme.system.DisplaySystem;
import com.jme.system.canvas.JMECanvas;
import com.jme.system.canvas.JMECanvasImplementor;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.Timer;
import com.jmex.awt.input.AWTKeyInput;
import com.jmex.awt.input.AWTMouseInput;
import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor;

import java.awt.Canvas;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.util.concurrent.Callable;

public class AwtGfxImplementor extends JMECanvasImplementor {

    private final GfxCanvas gfxCanvas;
    private final Node rootNode = new Node( "rootNode" );
    private Timer timer = null;

    public AwtGfxImplementor() throws Exception {

        gfxCanvas = new GfxCanvas( this, 800, 600 );

    public void doSetup() {

        gfxCanvas.setUpdateInput( false );

        setRenderer( DisplaySystem.getDisplaySystem().getRenderer() );
        getRenderer().setCamera( getRenderer().createCamera( 800, 600 ) );
        timer = Timer.getTimer();

    public void doUpdate() {
        rootNode.updateGeometricState( timer.getTimePerFrame(), true );
        GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE ).execute();

    public void doRender() {


        GameTaskQueueManager.getManager().getQueue( GameTaskQueue.RENDER ).execute();

        renderer.draw( rootNode );


    public Canvas getCanvas() {
        return gfxCanvas.getCanvas();

    public Node getRootNode() {
        return rootNode;

    private class GfxCanvas {

        private final JMECanvasImplementor implementor;
        private final Canvas gfxCanvas;

        public GfxCanvas( final JMECanvasImplementor imp, int width, int height ) throws Exception {
            this.implementor = imp;

            final DisplaySystem display = DisplaySystem.getDisplaySystem();

            display.registerCanvasConstructor( "AWT", LWJGLAWTCanvasConstructor.class );
            gfxCanvas = (Canvas) display.createCanvas( width, height );

            gfxCanvas.addComponentListener( new ComponentAdapter() {

                public void componentResized( ComponentEvent ce ) {
            } );

            gfxCanvas.addFocusListener( new FocusListener() {

                public void focusGained( FocusEvent arg0 ) {
                    ( (AWTKeyInput) KeyInput.get() ).setEnabled( true );
                    ( (AWTMouseInput) MouseInput.get() ).setEnabled( true );

                public void focusLost( FocusEvent arg0 ) {
                    ( (AWTKeyInput) KeyInput.get() ).setEnabled( false );
                    ( (AWTMouseInput) MouseInput.get() ).setEnabled( false );
            } );

            setImplementor( implementor );

            if( !KeyInput.isInited() ){
                KeyInput.setProvider( InputSystem.INPUT_SYSTEM_AWT );

            if( !MouseInput.isInited() ){
                MouseInput.setProvider( InputSystem.INPUT_SYSTEM_AWT );
                AWTMouseInput.setup( gfxCanvas, false );

            ( (AWTMouseInput) MouseInput.get() ).setEnabled( true );
            gfxCanvas.addMouseListener( (MouseListener) MouseInput.get() );
            gfxCanvas.addMouseWheelListener( (MouseWheelListener) MouseInput.get() );
            gfxCanvas.addMouseMotionListener( (MouseMotionListener) MouseInput.get() );

            ( (AWTKeyInput) KeyInput.get() ).setEnabled( true );
            KeyListener kl = (KeyListener) KeyInput.get();
            gfxCanvas.addKeyListener( kl );

            setTargetRate( 60 );
            setDrawWhenDirty( false );
            setUpdateInput( true );

        public Canvas getCanvas() {
            return gfxCanvas;

        public void setImplementor( JMECanvasImplementor impl ) {
            ( (JMECanvas) gfxCanvas ).setImplementor( impl );

        public void setUpdateInput( boolean doUpdate ) {
            ( (JMECanvas) gfxCanvas ).setUpdateInput( doUpdate );

        public int getTargetSyncRate() {
            return ( (JMECanvas) gfxCanvas ).getTargetSyncRate();

        public boolean isDrawWhenDirty() {
            return ( (JMECanvas) gfxCanvas ).isDrawWhenDirty();

        public boolean isUpdateInput() {
            return ( (JMECanvas) gfxCanvas ).isUpdateInput();

        public void makeDirty() {
            ( (JMECanvas) gfxCanvas ).makeDirty();

        public void setDrawWhenDirty( boolean whenDirty ) {
            ( (JMECanvas) gfxCanvas ).setDrawWhenDirty( whenDirty );

        public void setTargetRate( int fps ) {
            ( (JMECanvas) gfxCanvas ).setTargetRate( fps );

        public void exit() {
            ( (JMECanvas) gfxCanvas ).killGfxContext();

        private void doResize() {

            if( !implementor.isSetup() ){

            GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE ).enqueue(
                    new Callable() {

                        public Object call() {
                            implementor.resizeCanvas( gfxCanvas.getWidth(), gfxCanvas.getHeight() );
                            return null;
                    } );

Ok, thanks.

I post a patch and I believe it will be possible to commit it.

I supposed that Jme 2.0 is better, but we have several projects in jme1.0 and we can't migrate for the moment, not enougth time to update hundred of classes.

thanks for your help.