Swing/AWT/JavaFX 界面 Freezing/NullPointerException
Swing/AWT/JavaFX GUI Freezing/NullPointerException
我有一个 class 扩展应用程序:
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(); // initializes JavaFX environment
createGUI();
}
});
}
我这样做是为了希望解决每个 this question 的 swing/JavaFX 组件之间的任何问题。但是,当我单击一个将 JPanel 或 JFXPanel 添加到另一个 JPanel 的按钮时,如果它是 JFXPanel,它将执行一次就好了,但此后我再次尝试生成 JFXPanel 时它会失败,给出“线程“AWT-EventQueue-0”java.lang.NullPointerException”中的异常(但实际上总共需要 3 次才能出现此错误 - 第二次它将冻结,如果没有,则什么都不做)。这是按钮的相关代码:
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();
我多次调用 validate()
,因为它有时无法添加形状,其中一组调用最初修复了该错误。如果您解释哪个面板更适合我调用它,则可加分。
如果您觉得需要其余代码,我创建了一个 github 存储库 here.
编辑:
完整的堆栈跟踪 -
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.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.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.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 形状(请参阅堆栈跟踪的第 6 行 - at javafx.scene.shape.Shape3D.<init>(Shape3D.java:74)
),这可能是由于线程安全。我的一些修复包含在下面的答案中,但我没有提到,尽管我的代码被包装在 Runnable()
s“稍后调用”中,但我将特定的 JFXPanel 生成代码冗余嵌套在与以下代码相同的可运行结构中出色地。这可能有所帮助,但我不确定如何。
Platform.runLater(() -> {
try {
SwingUtilities.invokeLater(() -> {
drawingPanel.add(shapePanel);
frame.pack();
});
} catch (Exception e) {
e.printStackTrace();
}
});
已修复。我相信错误可能是,在从 JPanel drawingArea
中删除所有元素后,它不会立即 validate()
d,因此不支持向其添加元素。我还确保 JFXPanel 是这样输入的,而不是被转换为组件。我还确保每次通过 JPanel drawing
按下按钮时都会创建它添加到的 JPanel,以防它在之前的方法范围内由于某种原因很重要。参见:
go.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JPanel drawing = new JPanel();
// irrelevant
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JFXPanel(); // initializes JavaFX environment
if (selectedShape.getClass().getSuperclass().getSimpleName()
.equals("TwoDimensionalShape")) {
Component shapePanel = (Component) new PaintedShape(selectedShape).getPanel();
drawing.add(shapePanel);
} else {
JFXPanel shapePanel = (JFXPanel) new PaintedShape(selectedShape).getPanel();
Platform.runLater(() -> {
try {
SwingUtilities.invokeLater(() -> {
drawing.add(shapePanel);
frame.pack();
});
} catch (Exception e) {
e.printStackTrace();
}
});
}
drawingArea.removeAll();
drawingArea.validate();
drawingArea.add(drawing);
drawingArea.repaint();
frame.pack();
frame.setSize(new Dimension((int) (frame.getSize().getWidth()),
(int) (frame.getSize().getHeight() + PaintedShape.size.getHeight())));
frame.setLocationRelativeTo(null);
}
});
}
});
完整的代码以及更改推送到 git 回购协议,以供更多好奇。
我有一个 class 扩展应用程序:
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(); // initializes JavaFX environment
createGUI();
}
});
}
我这样做是为了希望解决每个 this question 的 swing/JavaFX 组件之间的任何问题。但是,当我单击一个将 JPanel 或 JFXPanel 添加到另一个 JPanel 的按钮时,如果它是 JFXPanel,它将执行一次就好了,但此后我再次尝试生成 JFXPanel 时它会失败,给出“线程“AWT-EventQueue-0”java.lang.NullPointerException”中的异常(但实际上总共需要 3 次才能出现此错误 - 第二次它将冻结,如果没有,则什么都不做)。这是按钮的相关代码:
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();
我多次调用 validate()
,因为它有时无法添加形状,其中一组调用最初修复了该错误。如果您解释哪个面板更适合我调用它,则可加分。
如果您觉得需要其余代码,我创建了一个 github 存储库 here.
编辑: 完整的堆栈跟踪 -
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.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.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.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 形状(请参阅堆栈跟踪的第 6 行 - at javafx.scene.shape.Shape3D.<init>(Shape3D.java:74)
),这可能是由于线程安全。我的一些修复包含在下面的答案中,但我没有提到,尽管我的代码被包装在 Runnable()
s“稍后调用”中,但我将特定的 JFXPanel 生成代码冗余嵌套在与以下代码相同的可运行结构中出色地。这可能有所帮助,但我不确定如何。
Platform.runLater(() -> {
try {
SwingUtilities.invokeLater(() -> {
drawingPanel.add(shapePanel);
frame.pack();
});
} catch (Exception e) {
e.printStackTrace();
}
});
已修复。我相信错误可能是,在从 JPanel drawingArea
中删除所有元素后,它不会立即 validate()
d,因此不支持向其添加元素。我还确保 JFXPanel 是这样输入的,而不是被转换为组件。我还确保每次通过 JPanel drawing
按下按钮时都会创建它添加到的 JPanel,以防它在之前的方法范围内由于某种原因很重要。参见:
go.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JPanel drawing = new JPanel();
// irrelevant
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JFXPanel(); // initializes JavaFX environment
if (selectedShape.getClass().getSuperclass().getSimpleName()
.equals("TwoDimensionalShape")) {
Component shapePanel = (Component) new PaintedShape(selectedShape).getPanel();
drawing.add(shapePanel);
} else {
JFXPanel shapePanel = (JFXPanel) new PaintedShape(selectedShape).getPanel();
Platform.runLater(() -> {
try {
SwingUtilities.invokeLater(() -> {
drawing.add(shapePanel);
frame.pack();
});
} catch (Exception e) {
e.printStackTrace();
}
});
}
drawingArea.removeAll();
drawingArea.validate();
drawingArea.add(drawing);
drawingArea.repaint();
frame.pack();
frame.setSize(new Dimension((int) (frame.getSize().getWidth()),
(int) (frame.getSize().getHeight() + PaintedShape.size.getHeight())));
frame.setLocationRelativeTo(null);
}
});
}
});
完整的代码以及更改推送到 git 回购协议,以供更多好奇。