More than one JMECanvas instance?

Hello everybody,

I was wondering… is it possible to get two different JMECanvas running in parallel embbeded in the same JFrame?? Let me explain my case. I have a class, called TDRenderer, which is implementing SimpleCanvasImpl. The code is:

public class TDRenderer extends SimpleCanvasImpl {

private static final Logger logger = Logger.getLogger(JMESwingTest.class


private ControlTDRenderer controller;

public TDRenderer(ControlTDRenderer controller) {

super(300, 300);

this.controller = controller;



public void simpleSetup() {

// Normal Scene setup stuff…

Quaternion rotQuat = new Quaternion();

Vector3f axis = new Vector3f(1, 1, 0.5f);


Vector3f max = new Vector3f(5, 5, 5);

Vector3f min = new Vector3f(-5, -5, -5);

// ---- LIGHTS

/** Attach the light to a lightState and the lightState to rootNode. /

DirectionalLight light3 = new DirectionalLight();

light3.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));

light3.setDirection(new Vector3f(1, 0, 1).normalize());


LightState lightState = renderer.createLightState();







public ControlTDRenderer getController() {

return controller;



public void simpleUpdate() {




Then there's a class, named TDRCanvas, which creates a TDRenderer object and a canvas to paint the TDRenderer object.

public class TDRCanvas extends Canvas {

private static final long serialVersionUID = 1L;

private static boolean initialized = false;

// JPanel contentPane;

// JPanel mainPanel = new JPanel();

private static Canvas comp = null;

private static JMECanvasImplementor impl;

private static ControlTDRenderer controller;

private static ArrayList<Canvas> allCanvas;

public static ControlTDRenderer getController() {

return controller;



  • public static Canvas getCanvas() { if (comp == null) { init(); // comp =
  • new TDRCanvas(WIDTH, HEIGHT); } return comp; }


    private static int WIDTH = 800;

    private static int HEIGHT = 600;

    private static void init() {

    allCanvas = new ArrayList<Canvas>();

    new Thread() { { setDaemon(true); }


      @Override public void run() { while (true) {


      for (Canvas canvas : allCanvas) { canvas.repaint(); }




      yield(); } } }.start();


    // Component initialization

    public static Canvas createTDRCanvas() {



// make the canvas:
comp = DisplaySystem.getDisplaySystem("lwjgl").createCanvas(WIDTH,

// add a listener... if window is resized, we can do something about
// it.
comp.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {

if (!initialized) {

AWTMouseInput.setup(comp, false);

initialized = true;
// AWTMouseInput.destroyIfInitalized();

// Important! Here is where we add the guts to the panel:
controller = new ControlTDRenderer();
impl = controller.getRenderer();

JMECanvas jmeCanvas = (JMECanvas) comp;


comp.setBounds(0, 0, WIDTH, HEIGHT);

// controller = ((TDRenderer) impl).getController();
return comp;

protected static void doResize() {
impl.resizeCanvas(comp.getWidth(), comp.getHeight());

public static int getWIDTH() {
return WIDTH;

public static void setWIDTH(int width) {
WIDTH = width;

public static int getHEIGHT() {
return HEIGHT;

public static void setHEIGHT(int height) {
HEIGHT = height;


The case is I'm creating two different Canvas, putting them in two JPanels and everthing is oK, but It seems when doing doRender an exception is thrown:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.jme.scene.state.lwjgl.LWJGLZBufferState.enableDepthTest(Unknown Source)
at com.jme.scene.state.lwjgl.LWJGLZBufferState.apply(Unknown Source)
at com.jme.renderer.lwjgl.LWJGLRenderer.clearBuffers(Unknown Source)
at com.jmex.awt.SimpleCanvasImpl.doRender(Unknown Source)
at com.jmex.awt.lwjgl.LWJGLCanvas.paintGL(Unknown Source)
at org.lwjgl.opengl.AWTGLCanvas.paint(
at sun.awt.RepaintArea.paintComponent(Unknown Source)
at sun.awt.RepaintArea.paint(Unknown Source)
at Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at Source)

While testing, I've tried to load the same model in both canvas and those where the results:

I was just wondering if what I'm trying to do is possible, or if I should leave the idea aside.

Thank you in advance!!!

Multiple contexts (and thus multiple canvases) are not supported by the texture manager. This makes using multiple canvases a bit tricky. But I think some guy on these forums managed to get it to work…

OK, great, thanks for the info (I was going mad with that). Do you think it is possible to have a JMECanvas and a SimpleGame running at the same time??

Thank u again for ur help

It's possible. But it has the same issues as two canvases :expressionless:

Ok, let me explain my case. What I'm trying to do is a game editor. The editor, based on swing, has a JMECanvas to show a low-detail preview of the scene. Then it is desirable to provide a button to launch the whole game (a class implementing BaseGame). Then when the user is done examining the game exits and comes back to the editor (JMECanvas). When I launch the game everything goes fine but textures. I don't mind if the JMECanvas works while the game runs, I just need one of them to run in every moment.

Do you think I could somehow reset the TextureManager or something like that when I launch the game and restore it later when I come back to the editor?.

Thanks a lot again.

Thanks God I got it!!!

TextureManager.clearCache() worked fine!!!

Thank you anyway!

The issue is not in TextureManager but in the DisplaySystem creation. Problem is that when you create more than 1 display they do not share a context which means textures available to one display are not available to the other. As a result you need to upload the same texture multiple times for each display. My display system (which I plan to release soon) is able to share a single context with multiple displays so only a single set of textures and displaylists can be used.