| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><meta name="keywords" content="documentation, gui"><title>JME3 Canvas in a Swing GUI</title><link rel="stylesheet" href="./asciidoctor.css">
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
- <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"><link rel="stylesheet" href="/home/travis/build/jMonkeyEngine/wiki/build/asciidoc/html5/jme3/advanced/twemoji-awesome.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/swing_canvas.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>JME3 Canvas in a Swing GUI</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#extending-simpleapplication">Extending SimpleApplication</a></li><li><a href="#main-and-runnable">Main() and Runnable()</a><ul class="sectlevel2"><li><a href="#creating-the-canvas">Creating the Canvas</a></li><li><a href="#creating-the-swing-frame">Creating the Swing Frame</a></li></ul></li><li><a href="#navigation">Navigation</a></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><p>3D games are typically played full-screen, or in a window that takes over the mouse and all inputs. However it is also possible to embed a jME 3 canvas in a standard Swing application.<br>
- This can be useful when you create some sort of interactive 3D viewer with a user interface that is more complex than just a HUD: For instance an interactive scientific demo, a level editor, or a game character designer.</p></div>
- <div class="ulist"><ul><li><p>Advantages:</p><div class="ulist"><ul><li><p>You can use Swing components (frame, panels, menus, controls) next to your jME3 game.</p></li><li><p>The NetBeans <abbr title="Graphical User Interface">GUI</abbr> builder is compatible with the jMonkeyEngine; you can use it it to lay out the Swing <abbr title="Graphical User Interface">GUI</abbr> frame, and then add() the jME canvas into it. Install the <abbr title="Graphical User Interface">GUI</abbr> builder via Tools → Plugins → Available Plugins.</p></li></ul></div></li><li><p>Disadvantages:</p><div class="ulist"><ul><li><p>You cannot use SimpleApplication’s default mouse capturing for camera navigation, but have to come up with a custom solution.</p></li></ul></div></li></ul></div>
- <div class="paragraph"><p>Here is the full <a href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/awt/TestCanvas.java">TestCanvas.java</a> code sample.</p></div></div></div>
- <div class="sect1"><h2 id="extending-simpleapplication">Extending SimpleApplication</h2><div class="sectionbody"><div class="paragraph"><p>You start out just the same as for any jME3 game: The base application, here SwingCanvasTest, extends <code>com.jme3.app.SimpleApplication</code>. As usual, you use <code>simpleInitApp()</code> to initialize the scene, and <code>simpleUpdate()</code> as event loop.<br>
- The camera’s default behaviour in SimpleApplication is to capture the mouse, which doesn’t make sense in a Swing window. You have to deactivate and replace this behaviour by <code>flyCam.setDragToRotate(true);</code> when you initialize the application:</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">void</span> simpleInitApp() {
- <span class="comment">// activate windowed input behaviour</span>
- flyCam.setDragToRotate(<span class="predefined-constant">true</span>);
- <span class="comment">// Set up inputs and load your scene as usual</span>
- ...
- }</code></pre></div></div>
- <div class="paragraph"><p>In short: The first thing that is different is the <code>main()</code> method. We don’t call start() on the SwingCanvasTest object as usual. Instead we create a Runnable() that creates and opens a standard Swing jFrame. In the runnable, we also create our SwingCanvasTest game with special settings, create a Canvas for it, and add that to the jFrame. Then we call startCanvas().</p></div></div></div>
- <div class="sect2"><h3 id="main-and-runnable">Main() and Runnable()</h3><div class="paragraph"><p>The Swing isn’t thread-safe and doesn’t allow us to keep the jME3 canvas up-to-date. This is why we create a runnable for the jME canvas and queue it in the AWT event thread, so it can be invoked “later in the loop, when Swing is ready with updating its own stuff.<br>
- In the SwingCanvasTest’s main() method, create a queued runnable(). It will contain the jME canvas and the Swing frame.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
- java.awt.EventQueue.invokeLater(<span class="keyword">new</span> <span class="predefined-type">Runnable</span>() {
- <span class="directive">public</span> <span class="type">void</span> run() {
- <span class="comment">// ... see below ...</span>
- }
- });
- }</code></pre></div></div>
- <div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p>Note that you have to use app.enqueue() when modifying objects in the scene from the AWT Event Queue like you have to use java.awt.EventQueue.invokeLater() from other threads (e.g. the update loop) when changing swing elements. This can get hairy quickly if you don’t have a proper threading model planned so you might want to use NiftyGUI as it is embedded in the update loop thread and is also cross-platform compatible (e.g. android etc.).</p></div></td></tr></table></div>
- <div class="sect2"><h3 id="creating-the-canvas">Creating the Canvas</h3><div class="paragraph"><p>Here in the <code>run()</code> method, we start the jME application, create its canvas, create a Swing frame, and add everything together.<br>
- Specify the com.jme3.system.AppSettings so jME knows the size of the Swing panel that we put it into. The application will not ask the user for display settings, you have to specify them in advance.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">AppSettings settings = <span class="keyword">new</span> AppSettings(<span class="predefined-constant">true</span>);
- settings.setWidth(<span class="integer">640</span>);
- settings.setHeight(<span class="integer">480</span>);</code></pre></div></div>
- <div class="paragraph"><p>We create our canvas application SwingCanvasTest, and give it the settings. We manually create a canvas for this game and configure the com.jme3.system.JmeCanvasContext. The method setSystemListener() makes sure that the listener receives events relating to context creation, update, and destroy.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">SwingCanvasTest canvasApplication = <span class="keyword">new</span> SwingCanvasTest();
- canvasApplication.setSettings(settings);
- canvasApplication.createCanvas(); <span class="comment">// create canvas!</span>
- JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication.getContext();
- ctx.setSystemListener(canvasApplication);
- <span class="predefined-type">Dimension</span> dim = <span class="keyword">new</span> <span class="predefined-type">Dimension</span>(<span class="integer">640</span>, <span class="integer">480</span>);
- ctx.getCanvas().setPreferredSize(dim);</code></pre></div></div>
- <div class="paragraph"><p>Note that we have not called start() on the application, as we would usually do in the main() method. We will call startCanvas() later instead.</p></div></div>
- <div class="sect2"><h3 id="creating-the-swing-frame">Creating the Swing Frame</h3><div class="paragraph"><p>Inside the run() method, you create the Swing window as you would usually do. Create an empty jFrame and add() components to it, or create a custom jFrame object in another class file (for example, by using the NetBeans <abbr title="Graphical User Interface">GUI</abbr> builder) and create an instance of it here.
- Which ever you do, let’s call the jFrame <code>window</code>.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">JFrame</span> window = <span class="keyword">new</span> <span class="predefined-type">JFrame</span>(<span class="string"><span class="delimiter">"</span><span class="content">Swing Application</span><span class="delimiter">"</span></span>);
- window.setDefaultCloseOperation(<span class="predefined-type">JFrame</span>.EXIT_ON_CLOSE);</code></pre></div></div>
- <div class="paragraph"><p>We create a standard JPanel inside the JFrame. Give it any Layout you wish – here we use a simple Flow Layout. Where the code sample says “Some Swing Component, this is where you add your buttons and controls.<br>
- The important step is to add() the canvas component into the panel, like all the other Swing components.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">JPanel</span> panel = <span class="keyword">new</span> <span class="predefined-type">JPanel</span>(<span class="keyword">new</span> <span class="predefined-type">FlowLayout</span>()); <span class="comment">// a panel</span>
- <span class="comment">// add all your Swing components ...</span>
- panel.add(<span class="keyword">new</span> <span class="predefined-type">JButton</span>(<span class="string"><span class="delimiter">"</span><span class="content">Some Swing Component</span><span class="delimiter">"</span></span>));
- ...
- <span class="comment">// add the JME canvas</span>
- panel.add(ctx.getCanvas());</code></pre></div></div>
- <div class="paragraph"><p>OK, the jFrame and the panel are ready. We add the panel into the jFrame, and pack everything together. Set the window’s visibility to true make it appear.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">window.add(panel);
- window.pack();
- window.setVisible(<span class="predefined-constant">true</span>);</code></pre></div></div>
- <div class="paragraph"><p>Remember that we haven’t called start() on the jME appliation yet? For the canvas, there is a special <code>startCanvas()</code> method that you must call now:</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">canvasApplication.startCanvas();</code></pre></div></div>
- <div class="paragraph"><p>Clean, build, and run!</p></div></div></div>
- <div class="sect1"><h2 id="navigation">Navigation</h2><div class="sectionbody"><div class="paragraph"><p>Remember, to navigate in the scene, click and drag (!) the mouse, or press the WASD keys. Depending on your game you may even want to define custom inputs to handle navigation in this untypical environment.</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-20 23:30:51 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#doc-search',
- debug: false // Set debug to true if you want to inspect the dropdown
- });</script></body></html>
|