Integrate Jmonkey Canvas into swing frame

Hi,
I’m trying to integrate the jme canvas to a swing frame in order to create an editor.
I encounter several problems. First of all, the canvas, which I try to add in the center of a border layout, is misplaced and overlaps on other components. But if I resize the frame, the canvas take the right place.
As well, if I set the viewport background color, the color is set properly in a first place. But when I resize the frame, the viewport background color is set back to the default black color.
While debuging, I check that the canvas was the same before and after resizing. The canvas position does not change either.
Before resize:


After resize:

Here a little snippet to reproduce the problem:

    import com.jme3.app.SimpleApplication;
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.shape.Box;
    import com.jme3.system.AppSettings;
    import com.jme3.system.JmeCanvasContext;
    import java.awt.BorderLayout;
    import java.awt.Canvas;
    import java.awt.Dimension;
    import java.awt.event.KeyEvent;
    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTabbedPane;
    import javax.swing.SwingUtilities;

    public class Maintest {

      private JFrame frame;

      public static void main(String[] args) {
        Maintest maintest = new Maintest();
        maintest.start();
      }


      public void start() {
        SimpleApplication jmeApp = new SimpleApplication() {
          @Override
          public void simpleInitApp() {
            Box b = new Box(1, 1, 1); // create cube shape
            Geometry geom = new Geometry("Box", b);  // create cube geometry from the shape
            Material mat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");  // create a simple material
            mat.setColor("Color", ColorRGBA.Blue);   // set color of material to blue
            geom.setMaterial(mat);                   // set the cube's material
            rootNode.attachChild(geom);
          }
        };
        jmeApp.setShowSettings(false);
        AppSettings settings = new AppSettings(true);
        settings.setAudioRenderer(null);
        jmeApp.setPauseOnLostFocus(false);
        jmeApp.setSettings(settings);
        jmeApp.createCanvas();
        jmeApp.startCanvas(true);

        while (jmeApp.getContext() == null) {

          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }

        }

        // window visible.
        SwingUtilities.invokeLater(() -> {
          frame = new JFrame("myframe");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          jmeApp.getViewPort().setBackgroundColor(ColorRGBA.Red);
          // position and size the main window...
          Dimension dimension = new Dimension(300, 400);
          Canvas jmeCanvas = ((JmeCanvasContext) jmeApp.getContext()).getCanvas();
          jmeCanvas.setSize(dimension);
          JTabbedPane tabbedPane = new JTabbedPane();
          BorderLayout mainBorderLayout = new BorderLayout();
          frame.setLayout(mainBorderLayout);
          JPanel northArea = new JPanel();
          northArea.setLayout(new BoxLayout(northArea, BoxLayout.X_AXIS));
          northArea.add(new JButton("toolbarButton"));
          northArea.add(new JLabel("NORTH"));
          northArea.setMinimumSize(new Dimension(-1, 100));
          frame.add(new JButton("toolbarButton"), BorderLayout.NORTH);
          frame.add(new JLabel("SOUTH"), BorderLayout.SOUTH);
          frame.add(new JLabel("EAST"), BorderLayout.EAST);
          frame.add(new JLabel("WEST"), BorderLayout.WEST);
          tabbedPane
              .addTab("Tab 1", null, jmeCanvas,
                  "Does nothing");
          tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
          frame.add(tabbedPane, BorderLayout.CENTER);
          frame.pack();
          // show the window.
          frame.setVisible(true);
        });
      }

    }

Do you see something wrong I’m doing?

I know swing changed this at some point so maybe it’s not required anymore… but I have a long history with swing and it always makes me uncomfortable to see things added directly to a JFrame instead of its content pane.

In some prototype stuff Nehon and I did a long time ago we had JME working just fine in spring.

2 Likes

Try to add jmeCanvas first to a JPanel then give the JPanel the size of the dimension of your canvas , then add the panel to the tabbed bar

EDIT: so this may help

1 Like

Thanks to your advices, I finish to get a working sample :

      import com.jme3.app.SimpleApplication;
      import com.jme3.material.Material;
      import com.jme3.math.ColorRGBA;
      import com.jme3.scene.Geometry;
      import com.jme3.scene.shape.Box;
      import com.jme3.system.AppSettings;
      import com.jme3.system.awt.AwtPanel;
      import com.jme3.system.awt.AwtPanelsContext;
      import com.jme3.system.awt.PaintMode;
      import java.awt.BorderLayout;
      import java.awt.Container;
      import java.awt.Dimension;
      import java.awt.event.KeyEvent;
      import javax.swing.BoxLayout;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JPanel;
      import javax.swing.JTabbedPane;
      import javax.swing.SwingUtilities;

      public class Maintest extends SimpleApplication {

        public static void main(String[] args) {
          Maintest maintest = new Maintest();
          maintest.setShowSettings(false);
          AppSettings settings = new AppSettings(true);
          settings.setCustomRenderer(AwtPanelsContext.class);
          maintest.setSettings(settings);
          maintest.start(true);
          while (maintest.getViewPort() == null) {

            try {
              Thread.sleep(100);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }

          }

          // window visible.
          SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("myframe");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            maintest.viewPort.setBackgroundColor(ColorRGBA.Red);
            Container rootpane = frame.getContentPane();
            // position and size the main window...
            AwtPanelsContext ctx = (AwtPanelsContext) maintest.getContext();
            AwtPanel jmePanel = ctx.createPanel(PaintMode.Accelerated);
            jmePanel.setPreferredSize(new Dimension(600, 480));
            jmePanel.setMinimumSize(new Dimension(400, 300));
            ctx.setInputSource(jmePanel);
            jmePanel.attachTo(true, maintest.getViewPort());
            jmePanel.attachTo(true, maintest.getGuiViewPort());
            JTabbedPane tabbedPane = new JTabbedPane();
            JPanel northArea = new JPanel();
            northArea.setLayout(new BoxLayout(northArea, BoxLayout.X_AXIS));
            northArea.add(new JButton("toolbarButton"));
            northArea.add(new JLabel("NORTH"));
            rootpane.add(northArea, BorderLayout.NORTH);
            rootpane.add(new JLabel("SOUTH"), BorderLayout.SOUTH);
            rootpane.add(new JLabel("EAST"), BorderLayout.EAST);
            rootpane.add(new JLabel("WEST"), BorderLayout.WEST);
            tabbedPane
                .addTab("Tab 1", null, jmePanel,
                    "Does nothing");
            tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
            rootpane.add(tabbedPane, BorderLayout.CENTER);
            frame.pack();
            // show the window.
            frame.setVisible(true);
          });
        }

        @Override
        public void simpleInitApp() {
          flyCam.setDragToRotate(true);
          Box b = new Box(1, 1, 1); // create cube shape
          Geometry geom = new Geometry("Box", b);  // create cube geometry from the shape
          Material mat = new Material(assetManager,
              "Common/MatDefs/Misc/Unshaded.j3md");  // create a simple material
          mat.setColor("Color", ColorRGBA.Blue);   // set color of material to blue
          geom.setMaterial(mat);                   // set the cube's material
          rootNode.attachChild(geom);
        }

      }

I did use the AWTPanel like in the Paul’s Spix library. The difference may be in the way the panel attach itself to the viewport.

1 Like