2017-08-16 4 views
0

Je développe une application de bureau JavaFX. Je veux y afficher des objets 3D Java.Comment intégrer un Canvas3D dans une application JavaFX?

La façon de faire cela, autant que je sache, est d'utiliser le SwingNode de JavaFX. Java 3d doit également être intégré dans un composant Swing. C'est donc un processus en deux étapes.

Intégration de Java 3D des objets avec Java Swing

Exemple complet et minimal composé du panneau, je l'intention de réutiliser dans l'application FX et un JFrame qui montre cela fonctionne:

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; 
    } 

} 

Intégration le BallPanel dans l'application 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); 
    } 

} 

Tout ce que je vois est un fond gris où la sphère devrait être. J'ai essayé quelques variations différentes sans aucune chance. Impossible de trouver quoi que ce soit en ligne sur cette intégration particulière entre les classes Java 3D et JavaFX.

Je sais que JavaFX a des graphiques 3D mais je ne les aime pas du tout.

connexes, sans solution, question:

How Can I embed java3d's Canvas3d in javafx layout?

+1

Je ne connais pas Java-3D. Le 'Canvas3D' est-il un composant léger (c'est-à-dire rendu par Swing, et non par le toolkit de fenêtrage natif)? Sinon, vous ne pourrez pas le rendre dans un 'SwingNode'. Notez également que vous devez créer le contenu du 'SwingNode' sur le thread de distribution d'événement AWT via' SwingUtilities.invokeLater (...) ': voir les documents [' SwingNode'] (http://docs.oracle.com/javase /8/javafx/api/javafx/embed/swing/SwingNode.html). –

+0

Ah, ça pourrait être ça. Apparemment, Canvas3D est un élément d'interface graphique lourd. Une solution de contournement? – DPM

+1

Je ne pense pas. 'SwingNode' est conçu pour une rétrocompatibilité avec les composants" pure swing "(c'est-à-dire les composants légers), mais JavaFX en général a été conçu à partir de zéro. Vous devez probablement utiliser JavaFX 3D si vous utilisez JavaFX. Si vous voulez aller sur la route de JavaFX, José Pereda (qui poste ici parfois) est probablement la personne à chercher pour de bons articles JavaFX 3d. –

Répondre

0

J'ai finalement réussi à le faire fonctionner en utilisant JCanvas3D. Le mérite de la suggestion revient à @gouessej. Merci beaucoup.

Voici la nouvelle méthode 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); 
    } 

En outre, comme James_D souligne dans les commentaires, Canvas3D n'a pas été le chemin à parcourir car il ne peut être rendu correctement dans un JavaFXSwingNode parce qu'il est un poids lourd composant.

Le SwingNode javadoc confirme:

La hiérarchie des composants contenus dans l'instance JComponent ne doit pas contenir de composants lourds, sinon peut SwingNode ne parviennent pas à peindre.

0

Si ces deux phrases. "Je développe une application de bureau JavaFX Dans ce que je veux afficher des objets java 3D" sont vraiment l'essence de ce que vous demandez ici, alors vous êtes complètement sur la mauvaise voie. JavaFX prend en charge les formes 3D en mode natif, donc à moins d'avoir des besoins très spécifiques, il n'y a pas besoin de Canvas3D et d'incorporation de Swing. Je viens de voir que vous avez dit que vous connaissez les graphiques 3D JavaFX mais vous ne l'aimez pas. Pourriez-vous être un peu plus précis sur ce que vous n'aimez pas?

+0

Bien sûr: 1. Il semble très laid par défaut et sans beaucoup de peaufinage 2. javafx 3d api manque de fonctions de haut niveau qui peuvent être trouvés dans j3d (peut-être tort à ce sujet, c'était mon impression quand j'ai essayé de faire des rotations et autres joyeusetés) 3. Je n'aime pas l'api, trop complexe 4. Quelque chose de très spécifique à mon application concerne les deux faces, où les ensembles de surfaces dupliquées ne s'afficheront pas correctement. Ce doit être un défaut javafx. Je ne peux pas expliquer correctement dans cet espace limité. C'était le briseur d'affaire. – DPM