I use JME integrated into a bigger software so it is a special canvas that some times is started.
To keep the GUI nice and responsive, I want to to all the starting up in a SwingWorker thread.
This is the MWE:
[java]
import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.util.concurrent.ExecutionException;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
public class Main extends JPanel {
private JmeDummy jme;
public static void main(String[] args) {
Main main = new Main();
main.init();
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(main);
frame.pack();
frame.setVisible(true);
}
private void init() {
// Create a regular text field.
final JTextField errorMsg = new JTextField();
JButton startButton = new JButton("Start 3D");
startButton.setVerticalTextPosition(AbstractButton.CENTER);
startButton.setHorizontalTextPosition(AbstractButton.LEADING); // aka LEFT, for left-to-right locales
startButton.setMnemonic(KeyEvent.VK_ENTER);
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// start 3D engine
SwingWorker worker = new SwingWorker() {
@Override
public Canvas doInBackground() {
jme = new JmeDummy();
System.out.println("in doInBackground");
return jme.getComponentAndStartIt();
}
@Override
public void done() {
removeAll();
try {
add(get());
Main.this.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
super.componentResized(e);
jme.resize(getBounds());
}
});
}
catch (InterruptedException | ExecutionException e1) {
e1.printStackTrace();
}
}
};
worker.execute();
}
});
this.add(startButton);
this.add(errorMsg);
}
}
[/java]
[java]
import java.awt.Canvas;
import java.awt.Rectangle;
import java.util.logging.Level;
import com.jme3.app.SimpleApplication;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
public class JmeDummy extends SimpleApplication {
private JmeCanvasContext ctx;
@Override
public void simpleInitApp() {
createApplicationAndCanvas();
}
private void createApplicationAndCanvas() {
AppSettings settings = new AppSettings(true);
settings.setWidth(500);
settings.setHeight(500);
settings.setAudioRenderer(null);
java.util.logging.Logger.getLogger("").setLevel(Level.WARNING);
setSettings(settings);
setShowSettings(false);
setDisplayStatView(false);
setDisplayFps(false);
createCanvas();
ctx = (JmeCanvasContext) getContext();
ctx.setSystemListener(this);
}
public Canvas getComponentAndStartIt() {
startCanvas();
return ctx.getCanvas();
}
public void resize(Rectangle bounds) {
ctx.getCanvas().setBounds(bounds);
}
}
[/java]
This is the error:
in doInBackground java.util.concurrent.ExecutionException: java.lang.NullPointerException at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252) at java.util.concurrent.FutureTask.get(FutureTask.java:111) at javax.swing.SwingWorker.get(SwingWorker.java:602) at pt.up.fe.dceg.neptus.plugins.r3d.Main$1$1.done(Main.java:76) at javax.swing.SwingWorker$5.run(SwingWorker.java:737) at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832) at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112) at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842) at javax.swing.Timer.fireActionPerformed(Timer.java:312) at javax.swing.Timer$DoPostEvent.run(Timer.java:244) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:682) at java.awt.EventQueue$3.run(EventQueue.java:680) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:691) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139) at java.awt.EventDispatchThread.run(EventDispatchThread.java:97) Caused by: java.lang.NullPointerException at com.jme3.app.Application.startCanvas(Application.java:442) at com.jme3.app.Application.startCanvas(Application.java:429) at pt.up.fe.dceg.neptus.plugins.r3d.JmeDummy.getComponentAndStartIt(JmeDummy.java:55) at pt.up.fe.dceg.neptus.plugins.r3d.Main$1$1.doInBackground(Main.java:69) at pt.up.fe.dceg.neptus.plugins.r3d.Main$1$1.doInBackground(Main.java:1) at javax.swing.SwingWorker$1.call(SwingWorker.java:296) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at javax.swing.SwingWorker.run(SwingWorker.java:335) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722)
Can I even do this wih JME?