如何在 JavaFX 应用程序中嵌入 Canvas3D?
How to embed a Canvas3D in a JavaFX application?
我正在开发 JavaFX 桌面应用程序。我想在其中显示一些 java 3D 对象。
据我所知,实现这一点的方法是使用 JavaFX 的 SwingNode。 Java 3d 也必须集成到 Swing 组件中。所以这是一个两步过程。
将 Java 3D 对象与 Java Swing 集成
由我打算在 FX 应用程序中重用的面板和显示它有效的 JFrame 组成的完整和最小示例:
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class JFrameWithCanvas3D extends JFrame {
public JFrameWithCanvas3D() {
super("Swing JFrame Wraps Canvas3D");
setLayout(new BorderLayout());
BallPanel panel = new BallPanel();
add(panel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@SuppressWarnings("unused")
@Override
public void run() {
new JFrameWithCanvas3D();
}
});
}
}
public class BallPanel extends JPanel {
public BallPanel() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(500, 500));
add(makeCanvas());
}
private static Canvas3D makeCanvas() {
BranchGroup group = new BranchGroup();
group.addChild(makeLight());
group.addChild(new Sphere(5));
Canvas3D canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse universe = new SimpleUniverse(canvas3D);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
universe.getViewingPlatform().getViewPlatformTransform().setTransform(viewTransform);
universe.addBranchGraph(group);
return canvas3D;
}
private static DirectionalLight makeLight() {
DirectionalLight light = new DirectionalLight(new Color3f(Color.WHITE), new Vector3f(-1.0f, -1.0f, -1.0f));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100));
return light;
}
}
在 JavaFX 应用程序中集成 BallPanel
public class FXAppWithSwingPanel extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(450, 450));
panel.add(new BallPanel(), BorderLayout.CENTER);
swingNode.setContent(panel);
Pane pane = new Pane();
pane.getChildren().add(swingNode);
stage.setScene(new Scene(pane, 500, 500));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我只看到球体所在的灰色背景。我尝试了几种不同的变体,但没有成功。无法在网上找到任何关于 Java 3D 类 和 JavaFX 之间的特定集成的信息。
我知道 JavaFX 有 3D 图形,但我不喜欢它们(一点也不喜欢)。
相关,未解决,问题:
How Can I embed java3d's Canvas3d in javafx layout?
如果这两句话"I'm developing a JavaFX desktop application. In it I want to display some java 3D objects."真的是你在这里问的本质,那你就完全走错了路。 JavaFX 原生支持 3D 形状,因此除非您有非常具体的要求,否则不需要任何 Canvas3D 和嵌入任何 Swing。
我刚看到你说你知道 JavaFX 3D 图形但你不喜欢它。你能更具体地说明你不喜欢什么吗?
我终于设法使用 JCanvas3D 使其工作。该建议归功于@gouessej。非常感谢。
这是新的 makeCanvas
方法:
private void makeCanvas() {
GraphicsConfigTemplate3D gCT = new GraphicsConfigTemplate3D();
JCanvas3D jCanvas3D = new JCanvas3D(gCT);
Dimension canvasDim = new Dimension(400, 400);
jCanvas3D.setPreferredSize(canvasDim);
jCanvas3D.setSize(canvasDim);
add(jCanvas3D, BorderLayout.CENTER);
Canvas3D canvas3D = jCanvas3D.getOffscreenCanvas3D();
View view = new View();
view.setPhysicalBody(new PhysicalBody());
view.setPhysicalEnvironment(new PhysicalEnvironment());
view.addCanvas3D(canvas3D);
ViewPlatform vp = new ViewPlatform();
view.attachViewPlatform(vp);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
TransformGroup viewTG = new TransformGroup();
viewTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
viewTG.setTransform(viewTransform);
viewTG.addChild(vp);
viewTG.addChild(makeLight());
viewTG.addChild(new Sphere(5));
BranchGroup group = new BranchGroup();
group.addChild(viewTG);
group.addChild(makeLight());
group.addChild(new Sphere(5));
VirtualUniverse vu = new VirtualUniverse();
Locale locale = new Locale(vu);
locale.addBranchGraph(group);
}
此外,正如 James_D 在评论中指出的那样,Canvas3D
不是可行的方法,因为它无法在 JavaFX
SwingNode
中正确呈现,因为它属于重量级组件。
The hierarchy of components contained in the JComponent instance
should not contain any heavyweight components, otherwise SwingNode may
fail to paint it.
我正在开发 JavaFX 桌面应用程序。我想在其中显示一些 java 3D 对象。
据我所知,实现这一点的方法是使用 JavaFX 的 SwingNode。 Java 3d 也必须集成到 Swing 组件中。所以这是一个两步过程。
将 Java 3D 对象与 Java Swing 集成
由我打算在 FX 应用程序中重用的面板和显示它有效的 JFrame 组成的完整和最小示例:
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class JFrameWithCanvas3D extends JFrame {
public JFrameWithCanvas3D() {
super("Swing JFrame Wraps Canvas3D");
setLayout(new BorderLayout());
BallPanel panel = new BallPanel();
add(panel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@SuppressWarnings("unused")
@Override
public void run() {
new JFrameWithCanvas3D();
}
});
}
}
public class BallPanel extends JPanel {
public BallPanel() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(500, 500));
add(makeCanvas());
}
private static Canvas3D makeCanvas() {
BranchGroup group = new BranchGroup();
group.addChild(makeLight());
group.addChild(new Sphere(5));
Canvas3D canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse universe = new SimpleUniverse(canvas3D);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
universe.getViewingPlatform().getViewPlatformTransform().setTransform(viewTransform);
universe.addBranchGraph(group);
return canvas3D;
}
private static DirectionalLight makeLight() {
DirectionalLight light = new DirectionalLight(new Color3f(Color.WHITE), new Vector3f(-1.0f, -1.0f, -1.0f));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100));
return light;
}
}
在 JavaFX 应用程序中集成 BallPanel
public class FXAppWithSwingPanel extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setPreferredSize(new Dimension(450, 450));
panel.add(new BallPanel(), BorderLayout.CENTER);
swingNode.setContent(panel);
Pane pane = new Pane();
pane.getChildren().add(swingNode);
stage.setScene(new Scene(pane, 500, 500));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我只看到球体所在的灰色背景。我尝试了几种不同的变体,但没有成功。无法在网上找到任何关于 Java 3D 类 和 JavaFX 之间的特定集成的信息。
我知道 JavaFX 有 3D 图形,但我不喜欢它们(一点也不喜欢)。
相关,未解决,问题:
How Can I embed java3d's Canvas3d in javafx layout?
如果这两句话"I'm developing a JavaFX desktop application. In it I want to display some java 3D objects."真的是你在这里问的本质,那你就完全走错了路。 JavaFX 原生支持 3D 形状,因此除非您有非常具体的要求,否则不需要任何 Canvas3D 和嵌入任何 Swing。
我刚看到你说你知道 JavaFX 3D 图形但你不喜欢它。你能更具体地说明你不喜欢什么吗?
我终于设法使用 JCanvas3D 使其工作。该建议归功于@gouessej。非常感谢。
这是新的 makeCanvas
方法:
private void makeCanvas() {
GraphicsConfigTemplate3D gCT = new GraphicsConfigTemplate3D();
JCanvas3D jCanvas3D = new JCanvas3D(gCT);
Dimension canvasDim = new Dimension(400, 400);
jCanvas3D.setPreferredSize(canvasDim);
jCanvas3D.setSize(canvasDim);
add(jCanvas3D, BorderLayout.CENTER);
Canvas3D canvas3D = jCanvas3D.getOffscreenCanvas3D();
View view = new View();
view.setPhysicalBody(new PhysicalBody());
view.setPhysicalEnvironment(new PhysicalEnvironment());
view.addCanvas3D(canvas3D);
ViewPlatform vp = new ViewPlatform();
view.attachViewPlatform(vp);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 20)); //move "back" a little
TransformGroup viewTG = new TransformGroup();
viewTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
viewTG.setTransform(viewTransform);
viewTG.addChild(vp);
viewTG.addChild(makeLight());
viewTG.addChild(new Sphere(5));
BranchGroup group = new BranchGroup();
group.addChild(viewTG);
group.addChild(makeLight());
group.addChild(new Sphere(5));
VirtualUniverse vu = new VirtualUniverse();
Locale locale = new Locale(vu);
locale.addBranchGraph(group);
}
此外,正如 James_D 在评论中指出的那样,Canvas3D
不是可行的方法,因为它无法在 JavaFX
SwingNode
中正确呈现,因为它属于重量级组件。
The hierarchy of components contained in the JComponent instance should not contain any heavyweight components, otherwise SwingNode may fail to paint it.