java.lang.IllegalStateException: Cannot run from EDT

TestSwingCanva >> Yea, I saw that, but I meant test code for restarting a SimpleGame (since it seems to work fine for you guys…).



I was talking about startCanvas() as it was throwing an exception,

How do you know that it was startCanvas() that is throwing the exception? createCanvas is throwing the exact same one…

Also, using startCanvas() does not throw the exception, but instead does nothing…

i.e.

[java]…

terrainViewer.createCanvas();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

…[/java]

From what i see in the example you have to create it, then attach it and then start it.

And that leads me back to my original problem. ie. That I cannot stop and re-create the SimpleGame (hence this thread and my first thread).

What did you try? Detaching, stopping? Just detaching… Somehow it should work ^^

Is it possible for you to make a simple test case that shows the issue?

@normen: Somehow, yes. But I don’t see how :stuck_out_tongue: Tried every possible combination…



@momoko: Yup, here goes:



panelMap3D: The JPanel to which I am attaching the canvas.

terrainViewer: The class extending SimpleGame



The following all happens as a Swing tab-change event gets fired (or any swing event for that matter. I tried the following with an

a prototype from the swing tutorial. Same problems).



Case 1:



[java] if (mainTabbedPane.getSelectedIndex() == 1) {

terrainViewer.stop();

} else {

if (terrainViewer != null) {

java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {

panelMap3D.removeAll();

terrainViewer.createCanvas();

canvasContext = (JmeCanvasContext) terrainViewer.getContext();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

}

});

}

}[/java]

Nothing happens. No exceptions, no crashes. The JPanel displays the frozen image of what the SimpleGame looked like just before I stopped it. I repeated the above with the line: terrainViewer.startCanvas(); omitted. Still the same problem.



Case 2:

[java]java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {

panelMap3D.removeAll();

terrainViewer = new TerrainViewer3D(manager); // Change from case 1

terrainViewer.createCanvas();

canvasContext = (JmeCanvasContext) terrainViewer.getContext();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

}

});[/java]

This results in no exception being thrown. Instead, the application just crashes.



Case 3:

(Calling outside the EDT):

[java]new Thread(new Runnable() {

public void run() {

panelMap3D.removeAll();

terrainViewer = new TerrainViewer3D(manager);

terrainViewer.createCanvas();

canvasContext = (JmeCanvasContext) terrainViewer.getContext();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

}

}).start();[/java]

Again, this results in no exception being thrown. Instead, the application just crashes.



Case 4:

[java]

new Thread(new Runnable() {

public void run() {

panelMap3D.removeAll();

terrainViewer.createCanvas();

canvasContext = (JmeCanvasContext) terrainViewer.getContext();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

}

}).start();

[/java]

Here, nothing happens. No exception, no crash. But also no canvas being painted to the panel.

I tried omitting the line terrainViewer.startCanvas();, but this to results in no canvas being painted.



Case 5:

[java]

new Thread(new Runnable() {



public void run() {

panelMap3D.removeAll();

settings = new AppSettings(true);

settings.setWidth(1151);

settings.setHeight(768);

terrainViewer = new TerrainViewer3D(manager);

terrainViewer.setSettings(settings);

terrainViewer.createCanvas();

canvasContext = (JmeCanvasContext) terrainViewer.getContext();

terrainViewer.startCanvas();

panelMap3D.add(canvasContext.getCanvas());

}

}).start();

[/java]

…Again, no exception is thrown. The application just crashes. Doing this from within the EDT (i.e.java.awt.EventQueue.invokeLater(new Runnable() {…) produces the same outcome.



I tried all of the above using both terrainViewer.stop() and terrainViewer.stop(true).

A test case would be a whole program in one file that shows the problem so Momoko doesnt need to create that himself.

Sorry. Here you go:

(relevant code in public void actionPerformed(ActionEvent e) { … } ).



[java]

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package test;



    import com.jme3.app.SimpleApplication;

    import com.jme3.material.Material;

    import com.jme3.math.Vector3f;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.shape.Box;

    import com.jme3.system.AppSettings;

    import com.jme3.system.JmeCanvasContext;

    import com.jme3.texture.Texture;

    import java.awt.Dimension;

    import java.awt.FlowLayout;

    import java.awt.event.ActionEvent;

    import java.awt.event.ActionListener;

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JPanel;



    /**
  • you can embed a jme canvas inside a swing application
  • @author pgi

    */

    public class SwingCanvasTest extends SimpleApplication {



    @Override

    public void simpleInitApp() {

    // activate windowed input behaviour

    flyCam.setDragToRotate(true);

    // display a cube

    Box boxshape1 = new Box(new Vector3f(-3f, 1.1f, 0f), 1f, 1f, 1f);

    Geometry cube = new Geometry(“My Textured Box”, boxshape1);

    Material mat_stl = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);

    Texture tex_ml = assetManager.loadTexture(“Interface/Logo/Monkey.jpg”);

    mat_stl.setTexture(“m_ColorMap”, tex_ml);

    cube.setMaterial(mat_stl);

    rootNode.attachChild(cube);

    }



    public static void main(String[] args) {

    java.awt.EventQueue.invokeLater(new Runnable() {



    public void run() {

    // create new JME appsettings

    AppSettings settings = new AppSettings(true);

    settings.setWidth(640);

    settings.setHeight(480);



    // create new canvas application

    final SwingCanvasTest canvasApplication = new SwingCanvasTest();

    canvasApplication.setSettings(settings);

    canvasApplication.createCanvas(); // create canvas!

    JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication.getContext();

    ctx.setSystemListener(canvasApplication);

    Dimension dim = new Dimension(640, 480);

    ctx.getCanvas().setPreferredSize(dim);



    // Create Swing window

    JFrame window = new JFrame(“Swing Application”);

    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



    // Fill Swing window with canvas and swing components

    JPanel panel = new JPanel(new FlowLayout()); // a panel

    panel.add(ctx.getCanvas()); // add JME canvas

    JButton bt = new JButton(“Swing Component”);

    bt.addActionListener(new ActionListener() {



    private boolean stopped = false;



    public void actionPerformed(ActionEvent e) {

    if (!stopped) {

    canvasApplication.stop();

    stopped = true;

    } else {

    java.awt.EventQueue.invokeLater(new Runnable() {



    public void run() {

    canvasApplication.start();

    }

    });

    }

    }

    });

    panel.add(bt); // add some Swing

    window.add(panel);

    window.pack();



    // Display Swing window including JME canvas!

    window.setVisible(true);

    canvasApplication.startCanvas();

    }

    });

    }

    }



    [/java]

You can’t stop() an application and then revive it again with start(). The canvas will get removed and the thread will wait for it to get displayed again to continue.

Yes I know, but I just inserted this as a placeholder for any of the 4 code snippets above. The correct way would be along the following lines:

  1. createCanvas();
  2. canvasContext = (JmeCanvasContext) foo.getContext();
  3. startCanvas();
  4. add(canvasContext.getCanvas())



    Anyway, none of this is relevant since not one of those approaches work for me :stuck_out_tongue:

Sorry for being a pain, but…anybody get this to work?

I can open and close the canvas in jMP (when i enable the close button). Look at how its done there (SceneViewerTopComponent/SceneApplication).

Thanks, I didn’t realize that there was a sample in jMP (never used it). Knowing this would have probably made this thread redundant :stuck_out_tongue: Anyway, I’ll give it a go :slight_smile:



SceneViewerTopComponent/SceneApplication – Are you referring to the jMP source? Or some project files somewhere part of the default jMP project?

Btw, running TestCanvas from within jMP won’t work. Throwing:

[java]INFO: EDT: Creating OGL thread.

Exception in thread “LWJGL Renderer Thread” java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path

at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1754)

at java.lang.Runtime.loadLibrary0(Runtime.java:823)

at java.lang.System.loadLibrary(System.java:1045)

at org.lwjgl.Sys$1.run(Sys.java:72)

at java.security.AccessController.doPrivileged(Native Method)

at org.lwjgl.Sys.doLoadLibrary(Sys.java:65)

at org.lwjgl.Sys.loadLibrary(Sys.java:81)

at org.lwjgl.Sys.(Sys.java:98)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:146)

at java.lang.Thread.run(Thread.java:680)[/java]

Can’t find the jMP code anywhere…and am unable to access it via svn…not sure what exactly you are referring to with “(SceneViewerTopComponent/SceneApplication)”…mind elaborating?

http://code.google.com/p/jmonkeyengine/source/browse/branches/jme3-gde/jme3-core/src/com/jme3/gde/core/scene/SceneApplication.java



http://code.google.com/p/jmonkeyengine/source/browse/branches/jme3-gde/jme3-core/src/com/jme3/gde/core/sceneviewer/SceneViewerTopComponent.java

1 Like

Thanks Normen. Got it to work :slight_smile:

Well, would be nice you post the solution :stuck_out_tongue:

You already did :stuck_out_tongue:



To those having problems in the future, you will have to override enqueue() just like normen did in SceneApplication. Then you won’t have those problems removing and re-attaching the SimpleGame application from the JPanel canvas.

[java] @Override

public Future enqueue(Callable callable) {

if (sceneActive) {

return super.enqueue(callable);

} else {

try {

final V value = callable.call();

return new Future() {



public boolean cancel(boolean mayInterruptIfRunning) {

return true;

}



public boolean isCancelled() {

return false;

}



public boolean isDone() {

return true;

}



public V get() throws InterruptedException, ExecutionException {

return value;

}



public V get(long timeout, TimeUnit unit) {

return value;

}

};

} catch (Exception e) {

e.printStackTrace();

}

return null;

[/java]