如何在JavaFX应用程序中嵌入Canvas3D?

时间:2017-08-16 11:50:25

标签: java swing javafx javafx-8 java-3d

我正在开发一个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;
   }

}

在BallFnel中集成JavaFX应用程序

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?

2 个答案:

答案 0 :(得分:0)

如果这两句话“我正在开发一个JavaFX桌面应用程序。在其中我想显示一些java 3D对象。”真的是你在这里要求的本质,那么你完全走错了路。 JavaFX原生支持3D形状,因此除非您有非常具体的要求,否则不需要任何Canvas3D并嵌入任何Swing。

我只是看到你说你知道JavaFX 3D图形,但你不喜欢它。你能不能更喜欢你不喜欢什么?

答案 1 :(得分:0)

我终于设法使用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中正确呈现,因为它是一个重量级组件。< / p>

SwingNode javadoc证实了这一点:

  

JComponent实例中包含的组件层次结构   不应该包含任何重量级组件,否则SwingNode可能   没有画它。