2017-08-16 103 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

相關問題