IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

JavaFX without EDT & bind java/JavaFX


Sujet :

JavaFX

  1. #1
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut JavaFX without EDT & bind java/JavaFX
    Bonjour à tous,
    J'aimerai utiliser javafx sans être dans l'EDT (juste utiliser le langage fx dans une autre api graphique).

    La seule façon de le faire pour moi est de définir des classes java qui font le coeur de l'API puis étendre ces classes en fx pour avoir une syntaxe purement fx.

    Le pb c'est que de base on est dans l'EDT.

    java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class ThreadDisplayer 
    {
    	public void whoAmI()
    	{
    		System.out.println("You are : "+Thread.currentThread().getName());
    	}
    }
    javafx :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    var displayer:ThreadDisplayer=new ThreadDisplayer();
     
    public function run(args:String[])
    {
    	displayer.whoAmI();
    }
    Et le résultat :
    You are : AWT-EventQueue-0
    Alors y a t il un moyen d'être dans un autre thread ?

  2. #2
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Pour ceux que ça intéresse voilà un lien sur le bind java/javafx
    http://blogs.sun.com/michaelheinrich...ects_in_javafx

    C lourd tout ça.

  3. #3
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Et voilà un petit exemple de bind java->javafx (bcp plus simple que javafx <-> java)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    import javax.swing.JFrame;
     
    public class FXJFrame
    {
    	 protected var f:JFrame=new JFrame();
     
    	 public-init var title:String on replace
    	 {
    	 	f.setTitle(title);
    	 }
     
    	 public-init var size:Integer[] on replace
    	 {
    	     if(sizeof(size)!=2)
    	     	throw new java.lang.IllegalArgumentException();
    	     f.setSize(size[0],size[1]);
    	 }
     
    	 public-init var visible:Boolean on replace
    	 {
    	 	 f.setVisible(visible);
    	 }
    }
     
    public function run(args:String[])
    {
      var frame:FXJFrame=FXJFrame
      {
          title:"Hello Binders"
          size:[100,100]
          visible:true
      };
     
      frame.size=[500,500];
    }
    Comme on peut le voir il y a forcément copie des données côté javafx.
    En concevant une API javafx/java il est surement impératif de séparer les données du traitement.

    Ici ça serait un truc du genre :
    Côté java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    public interface JFrameDataProvider
    {
       String getTitle();
       setTitle(String title);
       ...
    }
     
    public class JFrame
    {
       private JFrameDataProvider data;
     
       public JFrame (JFrameDataProvider data)
       {
         this.data=data;
       }
     
    }
    côté javafx
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class FXJFrame extends JFrameDataProvider
    {
       protected var f:JFrame=new JFrame(this);
     
       //ici on ajoute les champs title, size ....
     
    }
    Comme ça on a pas de duplication de données
    Évidement c'est un éxemple (on va pas reprogramer JFrame, de toute façon on peut pas).

    Qu'en pensez vous ?
    Ya des idées pour tourner en dehors de l'EDT ?

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Août 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 64
    Points : 75
    Points
    75
    Par défaut
    utiliser le langage fx dans une autre api graphique
    Quelle drôle d'idée !
    Ça serait peut-être plus simple de refaire un DSL... Voire de faire une description de données en Json ou Yaml.
    Ou si tu es courageux (et avec pas mal de temps libre...), tu prends le compilateur JavaFX (la seule partie open source...) et tu l'adaptes à tes besoins...

    Mais bon, en gros, je crains (sans être une autorité sur le sujet !) que ce ne soit pas possible, j'ai vu à plusieurs reprise que JavaFX est purement monothread.
    D'ailleurs, si on veut utiliser Async, si je ne m'abuse, le code tournant dans l'autre thread doit être du code Java, on ne peut pas utiliser JavaFX là...

  5. #5
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Moteur 3D jogl performant. Je ne pense vraiment pas qu'on aura un truc comme ça de base en fx avant pas mal de temps. Sun est surement confronté au même dilemne qu'Adobe sur le sujet.

    Fin le bind est facile! Un coup d'introspection sur les interfaces et le reste peut être auto généré. A part qq classes.

    Le pb reste que forcer la synchro EDT réduit les perfs en multi vue....

    Si j'ai répondu à ta question

  6. #6
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut


    Pour ceux qui en doutaient encore (y compris moi même), voilà un petit shot de la vue fx comme je le disais plus haut.

    C'est le petit lapin des démos jogl dans le moteur 3D dont je parlais (mais ça prouve que ça fonctionne).
    Le portage n'est pas loin



    Sans même modifier le classpath !
    Et là bcp de surprises (mais pas tant que ça)

    En animant le lapin :
    -Si on utilise un GLCanvas : consomation CPU 3%
    -Si on utilise un GLJPanel : consomation CPU 50% (j'suis en dual core)

    C'est la conf du viewer qui permet ça (GLCanvas ou GLJPanel).
    Vu la consommation CPU de javafx (d'un Stage), et le peu d'intérêt d'un GLJPanel (à part de rester en composant léger) il semble qu'ils utilisent un GLJPanel & co.

    Mais avec une vrai accélération 3D (GLCanvas), impossible de le visualiser en applet (c'est un peu normal car j'utilise pas de Stage).
    Si le runtime en cache est le même que celui du dev kit ya pas de raison de ne pas pouvoir avoir une vrai 3D dans un browser.

    Voilà mon code source pour ceux qui auraient une proposition pour l'applet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    public function run(args:String[])
    {
       var frame:JFrame=new JFrame();
       //create the behavior
       var be:DSBehavior=new DSBehavior();
       //the renderer
       var bck:GradBackGround=new GradBackGround(new GLColorRGB(new Color(3,3,64)),
        				new GLColorRGB(new Color(240,240,240)));
       var re:DrawerRenderer=new DrawerRenderer(bck,null);
     
       addDrawers(re);
     
       //add the samples listeners
       SamplesHandler.getDefault().add(new StdOutSamplesListener());
     
          //var viewer:View=new View(new AbstractViewportHandler(be,re),false,true,false);
       var viewer:View=new View(new AbstractViewportHandler(be,re),true,false,false);
       frame.getContentPane().add(viewer);
       frame.setSize(900,900);
       frame.setVisible(true);
    }
     
    function addDrawers(re:DrawerRenderer)
    {
       try 
       {
       var bunny:Bunny=new Bunny();
     
       re.add(new WireFrame(bunny));
       } 
       catch (e:IOException) 
       {
       e.printStackTrace();
       }
    }
    La décompilation fx runtime n'est pas loin (ou alors faut attendre les src de Sun).

    Et vive Java !


  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Février 2009
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 284
    Points : 409
    Points
    409
    Par défaut
    Ce que je vais dire est de l'ordre de l'empirique mais pour avoir des besoins spécifiques en Thread j'utilise des Runnable via des pools de thread... et ça fonctionne. Lorsque que l'on profile l'application le pool est bien la en dehors de l'EDT, comme bien d'autres choses d'ailleurs internes au SceneGraph.
    Donc à priori pas vraiment plus de différences entre javaFX et une appli Swing pour le multiThread. Après il faut bien se garder de modifier des objets qui sont déclarés dans le sceneGraph

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Août 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 64
    Points : 75
    Points
    75
    Par défaut
    galien, tes runnables font tourner du code JavaFX? (Parce que je crois que c'est le sujet du fil.)
    As-tu un exemple concret à montrer? (Un lien vers un ancien fil de discussion est OK, je sais que tu en as déjà parlé.)

  9. #9
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Bonjour,
    Je pense qu'il faut que je résume mon pb.

    Pourquoi ai je besoin du multithread ?

    Lorsque l'on fait un rendu GL, "public void display(GLAutoDrawable drawable)" est invokée.
    Si l'on est synchronisé avec Swing (cf javax.media.opengl.Threading) , tous les appels "display" de toutes les vues 3D se font dans l'EDT.

    Conséquence : si j'ai N vues 3D qui se dessinent en un temps T
    -Synchronisé : je dessine tout en N*T
    -Désynchronisé : je dessine tout en T

    Le frame rate est donc divisé par N.

    J'ai donc un thread par vu pour le rendu, l'EDT qui génère les évènements Swing pour l'intégration et une API synchronisée pour la modification de la scène.

    Où se pose le pb de synchro?

    Je n'ai pas besoin de faire appel à des thread côté fx car cette partie est déjà gérée côté java.
    Le problème est que pour afficher un objet il faut implémenter des interfaces qui informent du contenu des objets (globalement quelle forme à l'objet ?).

    Jusque là pas de pb (cf plus haut).
    Le hic c'est que ces interfaces sont appelée depuis le thread GL et pas par l'EDT.

    Le problème de synchro ne se pose pas entre fx et java, mais je ne sais pas si les objets fx sont fait pour être consommés exclusivement dans l'EDT ?

    Y a t il un verrou à appeler ?

  10. #10
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Concernant le lancement du viewer dans fx.

    L'utilisation de javafx.ext.swing.SwingComponent ne permet de lancer que la version GLJPanel et pas GLCanvas (comportement assez étonnant du Stage).

    Et toujours rien dans Firefox ou Safari.

    Comme je ne peux pas avoir accès au classes fx depuis java, il m'est impossible de lancer un Applet depuis java (et d'utiliser fx script en même temps).

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Février 2009
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 284
    Points : 409
    Points
    409
    Par défaut On va dire que je bricole...
    Voila un code qui ne "disfonctionne" pas de manière empirique.
    Apres tout javafx est du byteCode java au final donc je ne vois pas de raison que l'intégration de l'api concurent ne fonctionne pas
    Un code de test

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    def pool: ExecutorService = Executors.newCachedThreadPool();
    var text: String = "";
    var textToDisplay: String = "";
     
    var active = true;
    def sem: Semaphore = new Semaphore(1, true);
    function getThreadExecutionContext(): String {
        if(SwingUtilities.isEventDispatchThread()) "Thread inside EDT" else "Thread outside EDT"
    }
     
     
    def task: Runnable = Runnable {
        override function run() {
            try {
                while(active) {
                    try {
                        sem.acquire();
                        text = "{System.nanoTime()}";
                    } finally {
                        sem.release();
                    }
                    Thread.sleep(100);
                    println("from runnable loop: {getThreadExecutionContext()}");
                    FX.deferAction(
                        function(): Void {
                            try {
                                sem.acquire();
                                textToDisplay = "{text}";
                            } finally {
                                sem.release();
                            }
                            println("from defer action: {getThreadExecutionContext()}");
                        }
                    );
                }
     
            } catch(e: Exception) {
                println("{e}");
            }
        }
     
    }
    var activeUI: Boolean = active on replace {
        active = activeUI;
    };
    Stage {
        title : "ThreadTest"
        scene: Scene {
            width: 300
            height: 100
            content: [
                HBox {
                    nodeVPos: VPos.CENTER
                    content: [
                        CheckBox {
                            text: bind "{if (not activeUI) "in" else ""}active"
                            selected: bind activeUI with inverse
                        }
                        Button {
                            text: "Button"
                            action: function() {
                                pool.execute(task);
                            }
                        }
                        Label {
                            text: bind textToDisplay
                        }
     
                    ]
                }
            ]
        }
    }
    Au profiler en tout cas on voit bien le pool et son activité et tout plein de choses gérées par javaFX

  12. #12
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Très bien. Merci galien.
    Voilà les imports pour ceux qui veulent faire tourner l'exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    import java.util.concurrent.Executors;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Semaphore;
    import javax.swing.SwingUtilities;
    import java.lang.Runnable;
    import java.lang.Thread;
    import java.lang.System;
    import java.lang.Exception;
     
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.geometry.HPos;
    import javafx.geometry.VPos;
    import javafx.scene.layout.HBox;
    import  javafx.scene.control.*;
    Sur cet exemple si on fait le bind en dehors de l'EDT ça foire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ...
    try {
       sem.acquire();
       text = "{System.nanoTime()}";
       textToDisplay = "{text}";
    } finally {
        sem.release();
    }
    ...
    En fait le Stage se fige rapidement (alors qu'en swing un setText en dehors de l'EDT ne met pas à jour le texte c'est tout).
    Donc les bind doivent se faire forcément dans l'EDT (FX.deferAction).

  13. #13
    Membre averti

    Profil pro
    Inscrit en
    Février 2009
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 284
    Points : 409
    Points
    409
    Par défaut
    Le bind est en effet géré par le sceneGraph qui lui meme s'appui sur L'EDT.
    Cela changera surement dans PRISM

  14. #14
    Membre du Club Avatar de r1-1024
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    138
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 138
    Points : 68
    Points
    68
    Par défaut
    Une première introspection de javafx...

    Tout comme awt, fx est basé sur un Toolkit.
    -java.awt.Toolkit.getDefaultToolkit
    -com.sun.javafx.tk.Toolkit.get$TOOLKIT();

    On peut changer de Toolkit avec la propriété javafx.toolkit.
    Par défaut, le Toolkit utilisé est com.sun.javafx.tk.swing.SwingToolkit

    Ce Toolkit est utilisé pour fabriquer les objets FX (TKXXX qd dans l'api c'est XXX).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    import com.sun.javafx.tk.TKStage;
    import com.sun.javafx.tk.Toolkit;
    import com.sun.javafx.tk.swing.FrameStage;
     
    ....
     
    Toolkit tk=Toolkit.get$TOOLKIT();
    TKStage stage=tk.createTKStage(StageStyle.DECORATED);
    Container c=null;
     
    if(stage instanceof JApplet)
    {
    	c=((JApplet)stage).getContentPane();
    }
    else if(stage instanceof FrameStage)
    {
    	FrameStage fs=(FrameStage)stage;
    	c=fs.window;
    }
     
    ...
    stage.setSizeAndLocation(0, 0, 1000, 1000);
    stage.setVisible(true);
    On peut après customiser le container récupéré.

    Rq : Attention au $ de Toolkit.get$TOOLKIT()

    Toujours pareille le Canvas ne fonctionne pas en Applet.

    Au passage j'ai fait un shot de jogl applet sur java-net histoire de montrer le genre de pb d'intégration de GLCanvas dont je parlais plus haut.

    cf démo : https://jogl-demos.dev.java.net/applettest.html



    J'ai tiré le slide vers le bas (l'applet est en haut de la page).
    Notez le débordement du Canvas sur la barre d'url.

    Il y a le même genre de conflit qu'entre composants lourds et légers...
    D'où l'intérêt pour Sun du GLJPanel et son pbuffer qui reste un composant léger mais avec des perfs de merde

    Le mieux c'est d'ouvrir un nouvel onglet ... et l'applet 3D reste dans le nouvel onglet

    A noter que dans Safari ça ne le fait pas

Discussions similaires

  1. [CDI] Ingénieur de développement Java/JavaFX/PHP
    Par mehdiing dans le forum Demandes
    Réponses: 0
    Dernier message: 20/11/2013, 12h52
  2. Eclipse et Java & JavaFx
    Par weabow dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 24/10/2013, 14h52
  3. CSS et Java/JavaFX ?
    Par Beginner. dans le forum JavaFX
    Réponses: 4
    Dernier message: 10/04/2013, 08h46
  4. java & javaFX
    Par slim_java dans le forum JavaFX
    Réponses: 2
    Dernier message: 05/07/2009, 02h13
  5. Binding en JavaFX
    Par thomas.cadot dans le forum JavaFX
    Réponses: 5
    Dernier message: 24/03/2009, 10h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo