2017-08-16 99 views
0

我正在开发一个JavaFX桌面应用程序。其中我想显示一些Java 3D对象。如何在JavaFX应用程序中嵌入Canvas3D?

据我所知,这样做的方法是使用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?

+1

我不知道Java-3D。 Canvas3D是一个轻量级组件(即由Swing呈现,而不是由本地窗口工具包呈现的组件)?如果没有,你将无法在'SwingNode'中渲染它。另外请注意,您应该通过SwingUtilities.invokeLater(...)在AWT事件调度线程上创建'SwingNode'的内容:参见['SwingNode'文档](http://docs.oracle.com/javase /8/javafx/api/javafx/embed/swing/SwingNode.html)。 –

+0

啊,就是这样。显然Canvas3D是一个重量级的GUI元素。任何解决方法? – DPM

+1

我不这么认为。 'SwingNode'设计用于与“纯摆动”组件(即轻量级组件)的后兼容,但是通常JavaFX是从零开始设计的。如果您使用的是JavaFX,则可能必须使用JavaFX 3D。如果你想要去JavaFX路线,JoséPereda(有时候在这里发帖)可能是寻找好的JavaFX 3d文章的人。 –

回答

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没有去,因为它不能正确地在JavaFXSwingNode渲染,因为它是一个重量级的方式零件。

SwingNode javadoc证实了这一点:

包含在JComponent实例 不应包含任何重量级组件组件的层次结构,否则可SwingNode失败 画它。

0

如果这两句话。“我正在开发一个JavaFX桌面应用程序在这我想显示一些Java 3D对象”真的是你在这里要求的精髓,那么你完全处于错误的轨道上。 JavaFX本身支持3D形状,因此除非您有非常特殊的要求,否则不需要任何Canvas3D并嵌入任何Swing。

我只是看到你说你知道JavaFX 3D图形,但你不喜欢它。你能否更具体一些你不喜欢的东西?

+0

当然:1.默认情况下看起来非常丑陋,没有太多的调整2. javafx 3d api缺乏高级功能,可以在j3d(这可能是错误的,这是我的印象,当我试图做旋转和什么)3.我不喜欢api,太复杂4.一些非常具体的我的应用程序必须做双面的表面,其中重复表面组将无法正确显示。这必须是javafx缺陷。我无法在这个有限的空间里正确解释。这是交易断路器。 – DPM

相关问题