Swing与JavaFX混合开发多次创建JFXPanel出现空指针与界面冻结问题
Java Swing与JavaFX混合开发新增JFXPanel空指针异常问题
我有一个继承自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();
我的main/start方法代码如下:
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(); // 初始化JavaFX环境 createGUI(); } }); }
我参考了现有方案处理Swing与JavaFX组件的兼容问题。但现在点击按钮向JPanel添加JPanel或JFXPanel时,添加JFXPanel的操作第一次正常,后续再次尝试生成JFXPanel就会失败,抛出Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException异常(实际第三次点击才会出现报错,第二次点击要么界面冻结要么无响应)。按钮的相关代码如下:
JButton go = new JButton("Go"); go.addActionListener(new ActionListener() { // 不相关代码 System.out.println("Shape set parameters: " + selectedShape.setParameters(shapeParams)); SwingUtilities.invokeLater(new Runnable() { public void run() { new JFXPanel(); // 初始化JavaFX环境 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();
我多次调用validate()是因为之前偶尔会出现添加图形失败的问题,某一次加了这些调用后临时解决了该问题。希望能额外说明应该在哪个面板上调用这个方法更合理。完整代码已上传至GitHub仓库。
编辑:完整堆栈跟踪如下:
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)
编辑:进一步调试发现,PaintedShape.java中无法实例化新的JavaFX 3D图形(见堆栈跟踪第6行at javafx.scene.shape.Shape3D.<init>(Shape3D.java:74)),可能是线程安全问题。我将JFXPanel生成代码嵌套了如下的Runnable结构后问题缓解,暂不清楚具体原理:
Platform.runLater(() -> { try { SwingUtilities.invokeLater(() -> { drawingPanel.add(shapePanel); frame.pack(); }); } catch (Exception e) { e.printStackTrace(); } });
内容的提问来源于stack exchange,提问作者ganondork
相关产品推荐
相关产品推荐

