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 :

Montrer menu contextuel et récupérer ID de la file actuelle


Sujet :

JavaFX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Décembre 2013
    Messages : 49
    Par défaut Montrer menu contextuel et récupérer ID de la file actuelle
    Bonjour,

    Je voudrais montrer un Menu Contextuel en faisant "un clic" (no pas clic droit) sur une file quelconque de ma Tableview et récupérer une valeur de la file choisie, mais je reçois une erreur Null pointer.

    Le même code ci-dessous marche bien si je n'ajoute pas l'instruction pour demander que le menu contextuel soit affiché par un simple clic.

    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
           tableView.setRowFactory(
            new Callback<TableView<Person>, TableRow<Person>>() {
                public TableRow<Person> call(TableView<Person> tableView) {
                final TableRow<Person> row = new TableRow<>();
                final ContextMenu rowMenu = new ContextMenu();
                MenuItem editItem = new MenuItem("Edit");
                    editItem.setId("rpt01");
                    editItem.setOnAction((ActionEvent event) -> {
                        System.out.println("%%%%%"+editItem.getId());
                        });
                MenuItem removeItem = new MenuItem("Delete");
                    removeItem.setId("rpt02");
                     removeItem.setOnAction((ActionEvent event) -> {
    //Me renvoie Null, le code perd la file actuel
                        System.out.println("+++++"+row.getItem().getTest());
                        });
                    rowMenu.getItems().addAll(editItem, removeItem);
     
                    row.contextMenuProperty().bind(
                            Bindings.when(Bindings.isNotNull(row.itemProperty()))
                                    .then(rowMenu)
                                    .otherwise((ContextMenu)null));
    //--->Montrer le Menu Contextuel avec un simple clic… 
                    tableView.setOnMouseClicked((MouseEvent e) -> {
                        rowMenu.show(tableView, e.getScreenX(), e.getScreenY());
                   });
    //<--- en enlevante ce morceau de code ça marche, mais en faisant clic droit 
                    return row;
     
                }
     
            });
    Merci d'avance si quelqu'un peut me donner des idées pour résoudre cette situation.

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Je pense que le probleme vient du fait que la gestion du menu est placee dans le callback qui sert de factory et non pas dans la row.
    Ceci devrait mieux fonctionner je pense. Par contre on a 1 menu par ligne au lieu d'1 menu partage par toutes les lignes (meuh bon en bidouillant on doit pouvoir revenir a un menu partage du moment qu'on lui passe l'item de la ligne courante).

    PS : ici j'ai fait un test avec les proprietes systeme puisque je n'ai pas la classe Person bien sur.

    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
    public class Main extends Application {
     
        @Override
        public void start(Stage primaryStage) {
            final Properties properties = System.getProperties();
            final List<String> keys = new ArrayList(properties.stringPropertyNames());
            Collections.sort(keys);
            final TableView<String> tableView = new TableView();
            tableView.getItems().setAll(keys);
            keys.clear();
            final TableColumn<String, String> keyColumn = new TableColumn("Key");
            keyColumn.setCellValueFactory((TableColumn.CellDataFeatures<String, String> p) -> {
                final String key = p.getValue();
                return new SimpleStringProperty(key);
            });
            final TableColumn<String, String> valueColumn = new TableColumn("Value");
            valueColumn.setCellValueFactory((TableColumn.CellDataFeatures<String, String> p) -> {
                final String key = p.getValue();
                final String value = properties.getProperty(key);
                return new SimpleStringProperty(value);
            });
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            tableView.getColumns().setAll(keyColumn, valueColumn);
            tableView.setRowFactory((TableView<String> tv) -> {
                final TableRow<String> row = new TableRow<String>() {
                    final ContextMenu rowMenu = new ContextMenu();
     
                    {
                        final MenuItem editItem = new MenuItem("Edit");
                        editItem.setId("rpt01");
                        editItem.setOnAction((ActionEvent event) -> {
                            final String key = getItem();
                            System.out.printf("%%%%%% %s - %s", editItem.getId(), key).println();
                        });
                        MenuItem removeItem = new MenuItem("Delete");
                        removeItem.setId("rpt02");
                        removeItem.setOnAction((ActionEvent event) -> {
                            final String key = getItem();
                            System.out.printf("%%%%%% %s - %s", removeItem.getId(), key).println();
                        });
                        rowMenu.getItems().addAll(editItem, removeItem);
                        contextMenuProperty().bind(
                                Bindings.when(Bindings.isNotNull(itemProperty()))
                                .then(rowMenu)
                                .otherwise((ContextMenu) null));
                        setOnMouseClicked((MouseEvent e) -> rowMenu.show(tableView, e.getScreenX(), e.getScreenY()));
                    }
     
                    @Override
                    protected void updateItem(String t, boolean bln) {
                        super.updateItem(t, bln);
                    }
                };
                return row;
            });
            final StackPane root = new StackPane();
            root.getChildren().add(tableView);
            final Scene scene = new Scene(root, 600, 600);
            primaryStage.setTitle("Test TableView ContextMenu");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
     
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
    }
    Cool, je vais pouvoir ajouter un chapitre sur la redefinition des lignes dans TableView dans mon tutoriel en cours de redaction, j'avais jamais teste ca avant.
    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 averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Décembre 2013
    Messages : 49
    Par défaut
    Merci Bouyé,

    Ça marche, mais je ne comprends pas pourquoi il est si difficile de faire cela avec simple clic, alors que, en utilisant le menu contextuel avec clic droit on fait la même chose très facilement:
    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
     
        tableView.setRowFactory(
        new Callback<TableView<Person>, TableRow<Person>>() {
      @Override
      public TableRow<Person> call(TableView<Person> tableView) {
        final TableRow<Person> row = new TableRow<>();
        final ContextMenu rowMenu = new ContextMenu();
        MenuItem editItem = new MenuItem("Edit");
    //    editItem.setOnAction(...);
        MenuItem removeItem = new MenuItem("Delete");
        removeItem.setOnAction(new EventHandler<ActionEvent>() {
          @Override
          public void handle(ActionEvent event) {
            System.out.println("---->"+row.getItem().getTest());
            new ImprJasper("idpersona", row.getItem().getTest(), "rptB01", "PDF");
          }
        });
        rowMenu.getItems().addAll(editItem, removeItem);
     
        // only display context menu for non-null items:
        row.contextMenuProperty().bind(
          Bindings.when(Bindings.isNotNull(row.itemProperty()))
          .then(rowMenu)
          .otherwise((ContextMenu)null));
        return row;
      }
    });*/
    Avec Java (Swing), j'avais même une classe pour contrôler le Menu Contextuel, cette classe recevait la valeur de idKey et selon elle j'opérais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class PopupMenuExample extends JPanel implements ActionListener{  
    	public JPopupMenu popupMenu;
    	private long idKey;
    	private JPanel contentPane;
    
    	public PopupMenuExample(long idKey) {
    …
    Pour moi la valeur de idKey est essentielle, car selon elle je dois:
    a. Soit désactiver quelques options du menu contextuel, exemple (Java):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    		JMenuItem rptB01 = new JMenuItem("Copia Textual");
    		rptB01.setActionCommand("rptB01");
    		rptB01.addActionListener(this);
    
    ...
    		if (idKey==1) {
    			rptB01.setEnabled(false);	
    		}
    b. Soit imprimer des rapports:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	public void actionPerformed(ActionEvent event) {
    		String nomDoc = event.getActionCommand();
    		if (nomDoc == "rptB01") {
    	  	     new ImprJasper("idpersona", idKey, "rptB01", "PDF");
    }

    Dans une autre classe (ChercherPersonnes) lorsque l'utilisateur faisait clic sur une ligne de la table, je prennais la valeur idKey et avec elle en mémoire je montrais le Menu Contextuel et selon l'option choisie du menu je faisais ce qui avait été demandé.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	tablaResultado.addMouseListener(new MouseAdapter() {
    		public void mouseClicked(MouseEvent arg) {
    		        Point position = arg.getPoint();
    			int xposition = position.x;
    			int yposition = position.y;
    			long idKey = (Long) (tablaResultado.getModel().getValueAt(tablaResultado.getSelectedRow(),0));									
    			final PopupMenuExample menuContextuel = new  PopupMenuExample(idKey);		
    			menuContextuel.show(tablaResultado,xposition,yposition, idKey);		 
    			}	});
    Je pense que c'est possible de faire la même chose dans JavaFX, mais d'entrée je rencontre cette difficulté pour montrer un menu contextuel avec simple clic, récupérer sa valeur au moment de faire clic et opérer avec elle. Je suis donc un peu perdu…

    Merci pour ton aide.

  4. #4
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Ben, j'vois pas en quoi c'est pas possible de partager le menu contextuel ici. J'ai juste codé un truc vite fait ou chaque ligne a son propre menu mais ça ne doit pas être trop tordu de faire un truc du genre :

    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
     
    package test;
     
    import java.util.Optional;
    import javafx.event.ActionEvent;
    import javafx.scene.control.ContextMenu;
    import javafx.scene.control.MenuItem;
     
    /**
     *
     * @author Fabrice
     */
    public class RowContextMenu extends ContextMenu {
     
        public RowContextMenu() {
            final MenuItem editItem = new MenuItem("Edit");
            editItem.setId("rpt01");
            editItem.setOnAction((ActionEvent event) -> item.ifPresent((String item) -> System.out.printf("%%%%%% %s - %s", editItem.getId(), item).println()));
            MenuItem removeItem = new MenuItem("Delete");
            removeItem.setId("rpt02");
            removeItem.setOnAction((ActionEvent event) -> item.ifPresent((String item) -> System.out.printf("%%%%%% %s - %s", removeItem.getId(), item).println()));
            getItems().addAll(editItem, removeItem);
        }
     
        private Optional<String> item = Optional.empty();
     
        public void setItem(final String value) {
            item = Optional.ofNullable(value);
        }
    }
    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
    82
    83
    package test;
     
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Properties;
    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.scene.Scene;
    import javafx.scene.control.ContextMenu;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableRow;
    import javafx.scene.control.TableView;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
     
    /**
     *
     * @author Fabrice
     */
    public class Main extends Application {
     
        @Override
        public void start(Stage primaryStage) {
            final Properties properties = System.getProperties();
            final List<String> keys = new ArrayList(properties.stringPropertyNames());
            Collections.sort(keys);
            final TableView<String> tableView = new TableView();
            tableView.getItems().setAll(keys);
            keys.clear();
            final TableColumn<String, String> keyColumn = new TableColumn("Key");
            keyColumn.setCellValueFactory((TableColumn.CellDataFeatures<String, String> p) -> {
                final String key = p.getValue();
                return new SimpleStringProperty(key);
            });
            final TableColumn<String, String> valueColumn = new TableColumn("Value");
            valueColumn.setCellValueFactory((TableColumn.CellDataFeatures<String, String> p) -> {
                final String key = p.getValue();
                final String value = properties.getProperty(key);
                return new SimpleStringProperty(value);
            });
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            tableView.getColumns().setAll(keyColumn, valueColumn);
            final RowContextMenu rowContextMenu = new RowContextMenu();
            tableView.setRowFactory((TableView<String> tv) -> {
                final TableRow<String> row = new TableRow<String>() {
                    final ContextMenu rowMenu = new ContextMenu();
     
                    {
    //                    contextMenuProperty().bind(
    //                            Bindings.when(Bindings.isNotNull(itemProperty()))
    //                            .then(rowContextMenu)
    //                            .otherwise((RowContextMenu) null));
                        setOnMouseClicked((MouseEvent e) -> {
                            rowContextMenu.setItem(getItem());
                            rowContextMenu.show(tableView, e.getScreenX(), e.getScreenY());
                        });
                    }
     
                    @Override
                    protected void updateItem(String t, boolean bln) {
                        super.updateItem(t, bln);
                    }
                };
                return row;
            });
            final StackPane root = new StackPane();
            root.getChildren().add(tableView);
            final Scene scene = new Scene(root, 600, 600);
            primaryStage.setTitle("Test TableView ContextMenu");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
     
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            launch(args);
        }
    }
    Ça marche même très bien (chez moi).

    Swing et JavaFX ne fonctionne pas tout à fait pareil pour ce genre de controles :
    • Swing a un unique renderer (un par type d'objet contenu dans les colonne pour une JTable si mes souvenirs sont bons) qui est appliqué sur l'intégralité des lignes du composant (même celles hors écran, je te laisse imaginer le désastre que ça peut être dans des JList ou JTable de très très grande taille).
    • JavaFX a une cellule par ligne (RowCell) qui contient une cellule (la TableCell qui affiche l'objet à l'écran) par colonne visible visible à l'écran (donc au total on a <nb ligne visible> * cellule de ligne et <nb ligne visible> * <nb colonne visible> cellule de valeur et pas plus).


    EDIT - si tu veux faire un popup qui a accès à une valeur particulière d'une colonne sur une ligne donnée, c'est sur la table cell chargée d'afficher la valeur qu'il faut le mettre donc il va falloir dupliquer la gestion du popup sur chaque table cell de chaque colonne, ce qui n'est pas très dur maintenant que le popup est partageable.
    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

  5. #5
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Décembre 2013
    Messages : 49
    Par défaut
    Bouye, je tiens à te remercier infinement, cela marche parfaitement pour mes besoins.

    Grand merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2010] Récupérer le contrôle actif sur menu contextuel
    Par guen dans le forum VBA Access
    Réponses: 3
    Dernier message: 20/11/2013, 09h43
  2. [Débutant] DXTreeList : Ajouter menu contextuel et récupérer item clicé (pour suppression)
    Par Zoups dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 12/06/2012, 16h51
  3. Réponses: 8
    Dernier message: 17/04/2012, 17h05
  4. Réponses: 2
    Dernier message: 21/02/2010, 04h44
  5. Réponses: 41
    Dernier message: 11/12/2009, 11h24

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