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 :

[Débutant] Menu progressif en JavaFX


Sujet :

JavaFX

  1. #1
    Membre régulier
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Octobre 2009
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2009
    Messages : 167
    Points : 118
    Points
    118
    Par défaut [Débutant] Menu progressif en JavaFX
    Je débute en JavaFx et je développe une appli Java, qui intègre certaines fonctionnalités de Fx.

    Je voudrais reproduire les effets JavaScript des menus (ouverture progressive vers le bas, en douceur) avec Fx, dans le cadre d'une appli Java (je peux écrire le frontal en Fx, pas de Pb). Est-ce possible ?

    Christian

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Mouai bof, c'est pas génial avec l'API actuelle.

    Déjà les Menu ne sont pas ajoutés tels quel dans la MenuBar mais servent a créer des MenuBarButton qui sont une classe privée de la classe MenuBarSkin (elle-même dans l'API privee)... donc de ce cote-la c'est mal barré.

    Sinon, j'ai tenté de redéfinir le skin des ContextMenu attaches a des MenuBar. Attention, c'est du code JavaFX 8 :

    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    .menu-bar .context-menu {
        -fx-skin: "test.ExpandMenuSkin";
    }

    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
    75
    76
    77
    78
    79
    80
    81
    package test;
     
    import javafx.animation.KeyFrame;
    import javafx.animation.KeyValue;
    import javafx.animation.Timeline;
    import javafx.application.Platform;
    import javafx.beans.binding.Bindings;
    import javafx.beans.binding.ObjectBinding;
    import javafx.beans.value.ObservableValue;
    import javafx.event.ActionEvent;
    import javafx.scene.Node;
    import javafx.scene.control.ContextMenu;
    import javafx.scene.control.Skin;
    import javafx.util.Duration;
     
    /**
     *
     * @author fabriceb
     */
    public class ExpandMenuSkin extends com.sun.javafx.scene.control.skin.ContextMenuContent implements Skin<ContextMenu> {
     
        private ContextMenu contextMenu;
        private ObjectBinding<Boolean> contextMenuShowing;
     
        public ExpandMenuSkin(final ContextMenu contextMenu) {
            super(contextMenu);
            getStyleClass().add("context-menu");
            this.contextMenu = contextMenu;
            contextMenuShowing = Bindings.<Boolean>select(sceneProperty(), "window", "showing");
            contextMenuShowing.addListener(this::popupVisibleListener);
        }
     
        @Override
        public ContextMenu getSkinnable() {
            return contextMenu;
        }
     
        @Override
        public Node getNode() {
            return this;
        }
     
        @Override
        public void dispose() {
            if (contextMenu == null) {
                contextMenu = null;
            }
            if (contextMenuShowing != null) {
                contextMenuShowing.removeListener(this::popupVisibleListener);
                contextMenuShowing.dispose();
                contextMenuShowing = null;
            }
            super.dispose();
        }
     
        ////////////////////////////////////////////////////////////////////////////
        private void popupVisibleListener(ObservableValue<? extends Boolean> observableValue, Boolean oldValue, Boolean newValue) {
            System.out.printf("%s -> %s", oldValue, newValue).println();
            if (newValue) {
                // At this stage the popup has no height yet, so we run later after it has been made visible onscreen.
                Platform.runLater(() -> {
                    System.out.println(getHeight());
                    expand();
                });
            }
        }
     
        private void expand() {
            final double startHeight = 0;
            final double endHeight = getHeight();
            final Duration duration = Duration.millis(250);
            Timeline animation = new Timeline(
                    new KeyFrame(Duration.ZERO, new KeyValue(prefHeightProperty(), startHeight)),
                    new KeyFrame(duration, new KeyValue(prefHeightProperty(), endHeight)));
            animation.setOnFinished((final ActionEvent actionEvent) -> {
                setPrefHeight(endHeight);
                layout();
            });
            animation.play();
        }
    }
    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
    package test;
     
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Menu;
    import javafx.scene.control.MenuBar;
    import javafx.scene.control.MenuItem;
    import javafx.scene.control.SeparatorMenuItem;
    import javafx.scene.layout.BorderPane;
    import javafx.stage.Stage;
    import org.scenicview.ScenicView;
     
    /**
     *
     * @author fabriceb
     */
    public class Main extends Application {
     
        @Override
        public void start(Stage primaryStage) {
            MenuItem openItem = new MenuItem("Open...");
            MenuItem saveItem = new MenuItem("Save");
            MenuItem saveAsItem = new MenuItem("Save As...");
            MenuItem exitItem = new MenuItem("Exit");
            MenuItem textItem = new MenuItem("Text");
            MenuItem xlItem = new MenuItem("Microsoft Excel");
            Menu exportMenu = new Menu("Export");
            exportMenu.getItems().setAll(textItem, xlItem);
            Menu fileMenu = new Menu("File");
            fileMenu.getItems().setAll(openItem, new SeparatorMenuItem(), saveItem, saveAsItem, new SeparatorMenuItem(), exportMenu, new SeparatorMenuItem(), exitItem);
            MenuItem aboutItem = new MenuItem("About");
            Menu aboutMenu = new Menu("About");
            aboutMenu.getItems().add(aboutItem);
            MenuBar menuBar = new MenuBar();
            menuBar.getMenus().setAll(fileMenu, aboutMenu);
            BorderPane root = new BorderPane();
            root.setTop(menuBar);
     
            Scene scene = new Scene(root, 300, 250);
            scene.getStylesheets().add(getClass().getResource("Main.css").toExternalForm());
     
            primaryStage.setTitle("Hello World!");
            primaryStage.setScene(scene);
            primaryStage.show();
            ScenicView.show(scene);
        }
     
        /**
         * The main() method is ignored in correctly deployed JavaFX 
         * application. main() serves only as fallback in case the 
         * application can not be launched through deployment artifacts,
         * e.g., in IDEs with limited FX support. NetBeans ignores main().
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
     
    }
    Mais ce n'est pas génial non-plus :
    1. Bien que l'API Skin et Skinnable soit publique dans JavaFX8, les skins des composants de base sont, elles, toujours définie dans les packages de l'API privée, pour le moment.
    2. Actuellement le Binding génère une NullPointerException au début dans les logs. D'un cote, c'est normal vu que ni la Scene, ni la Window ne sont initialisée au debut mais bon, c'est silencieux dans le JDK7 et j’espère que c'est visible dans le JDK8 uniquement pour le deboggage de la beta et que ca redeviendra silencieux dans la version finale...
    3. Comme d'hab il faut s'arranger pour afficher le truc avant sinon il n'a pas de taille (d’où le Platform.runLater()).
    4. Le ContextMenu affiche une petite flèche servant a faire scroller le contenu du menu verticalement lorsque la hauteur du menu n'est pas suffisante pour afficher complétement son contenu. Or cette flèche est visible durant l'animation. Parfois même, elle persiste a la fin de l'animation (souvent quand le menu est assez petit verticalement quand il ne dispose que de 1-3 entrées) et il faut passer le curseur par dessus le menu pour qu'elle disparaisse (c'est la raison pour laquelle j'ai rajoute une action a la fin de l'animation mais, au final, ça ne résout pas le problème).
    5. Même en changeant le code pour le rendre compatible JDK7, je pense que ça ne marchera pas en Java 7 compte tenu de la manière dont les CSS fonctionnent dans JavaFX 2.2 (le ContextMenu n'est pas attache a la MenuBar)


    Je me demande si, sur le coup, ca ne vaudra pas mieux d'écrire son propre contrôle customisé de MenuBar en s'inspirant du code source de MenuBarSkin mais bon ca doit etre un boulot de longue haleine aussi. Our alors en surchargeant les methodes qu'il faut dans ContextMenuContent pour eviter de faire apparaitre cette flèche. Ou en bidouillant encore plus les CSS pour essayer de la rendre invisible....
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Membre régulier
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Octobre 2009
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2009
    Messages : 167
    Points : 118
    Points
    118
    Par défaut
    Un grand merci pour ce travail remarquable.

    Je teste tout cela de suite.

    Christian

Discussions similaires

  1. [Débutant] menu de recherche javascript
    Par azou_gold dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 06/10/2008, 16h22
  2. Menu dynamique javascript avec frame
    Par cosycorner dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 07/02/2007, 14h53
  3. [Débutant]Menu Diaporama XML
    Par Totomanator dans le forum Flash
    Réponses: 6
    Dernier message: 04/01/2007, 23h45
  4. [Débutant] Menu contextuel.
    Par Baban29 dans le forum VC++ .NET
    Réponses: 16
    Dernier message: 12/12/2006, 15h00
  5. [Débutant] Menu horizontal
    Par badboys206s16 dans le forum Flash
    Réponses: 2
    Dernier message: 05/12/2006, 14h47

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