I have a class that extends Application:
public class IO extends Application {
private static JFrame frame = new JFrame("Shapes");;
private final JPanel content = new JPanel();
private final JPanel drawingArea = new JPanel();
my main/start method:
public static void main(String[] args) {
Application.launch(args);
}
public void start(Stage primaryStage) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JFXPanel(); // initializes JavaFX environment
createGUI();
}
});
}
I've done this to hopefully resolve any troubles between the swing/JavaFX components per this question. However, when I click a button that adds either a JPanel or a JFXPanel to another JPanel, if it was the JFXPanel, it will perform once just fine, but it will fail anytime thereafter that I try to generate a JFXPanel again, giving an "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException" (but it actually takes 3 times total for this error to appear - the second time it will freeze, and if it doesn't, it does nothing). Here's the relevant code for the button:
JButton go = new JButton("Go");
go.addActionListener(new ActionListener() {
// irrelevant code
System.out.println("Shape set parameters: " + selectedShape.setParameters(shapeParams));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JFXPanel(); // initializes JavaFX environment
Component shapePanel = (Component) new PaintedShape(selectedShape).getPanel();
drawingArea.add(shapePanel);
// drawingArea.add(new JLabel("Test"));
// drawingArea.repaint();
shapePanel.repaint();
shapePanel.validate();
drawingArea.repaint();
drawingArea.validate();
frame.pack();
frame.setSize(new Dimension((int) (frame.getSize().getWidth() + PaintedShape.size.getWidth()),
(int) (frame.getSize().getHeight() + PaintedShape.size.getHeight())));
frame.setLocationRelativeTo(null);
}
});
}
});
params.add(go);
content.validate();
I call validate()
a bunch of times because it was failing to add shapes sometimes, and one of those sets of calls initially fixed that error. Bonus points if you explain which panel is more relevant to call it on for me.
If you feel you need the rest of the code, I created a github repo here.
Edit: full stacktrace -
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.sun.javafx.tk.quantum.QuantumToolkit.isSupported(QuantumToolkit.java:1153)
at com.sun.javafx.application.PlatformImpl.isSupportedImpl(PlatformImpl.java:809)
at com.sun.javafx.application.PlatformImpl.isSupported(PlatformImpl.java:482)
at javafx.application.Platform.isSupported(Platform.java:168)
at javafx.scene.shape.Shape3D.<init>(Shape3D.java:74)
at javafx.scene.shape.Cylinder.<init>(Cylinder.java:89)
at shapes.PaintedShape.painted3DShapePanel(PaintedShape.java:96)
at shapes.PaintedShape.<init>(PaintedShape.java:51)
at shapes.IO$1$1$1.run(IO.java:215)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Edit:
Debugging further lead me to discover that it was not possible to instantiate any new three dimensional javafx shape in PaintedShape.java (see line 6 of the stack trace - at javafx.scene.shape.Shape3D.<init>(Shape3D.java:74)
), possibly due to thread safety. Some of my fixes are included in my answer below, but I didn't mention that, despite my code being wrapped in Runnable()
s "invoked later", I redundantly nested the specific JFXPanel generating code in the same runnable structure as well. This may have helped, though I'm not exactly sure how.
Platform.runLater(() -> {
try {
SwingUtilities.invokeLater(() -> {
drawingPanel.add(shapePanel);
frame.pack();
});
} catch (Exception e) {
e.printStackTrace();
}
});