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 :

Extraire les coordonnées d'un point sur un graphe LineChart


Sujet :

JavaFX

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 48
    Par défaut Extraire les coordonnées d'un point sur un graphe LineChart
    Bonjour,

    Je développe en JavaFX une interface graphique dans laquelle des séries de données sont affichées dans un graphique ("linechart").
    J'ai besoin de créer une fonction qui permet à l'utilisateur de récupérer les coordonnées d'un point pour une série de données spécifique.
    Cette fonction doit être désactivable.

    Voici une brève description de la fonction que je souhaite développer. Lorsque l'utilisateur active cette option (en cliquant sur un bouton de l'interface) et déplace la souris sur le graphe, un trait vertical suit le déplacement de la souris. Lorsque l'utilisateur à cliqué sur un endroit du graphe, l’abscisse du point sélectionné est retournée au programme qui exploitera cette info.

    Pour commencer, je veux simplement extraire les coordonnées d'un point correspondant à l'endroit où l'utilisateur a cliqué.
    Pour cela, j'ai créé un bouton (boutonSelectedValueInGraph)qui gère l'appel et l'activation de cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    boutonSelectedValueInGraph.setOnAction(new EventHandler<ActionEvent>() {
    						@Override 
    						public void handle(ActionEvent event) {
    							UserSelectValue();
    							x1BaselinetextInput.setText(selectedValue.toString());
    						}
    					});
    "x1BaselinetextInput" correspond à un champ dans lequel l’abscisse du point choisi sera affiché. "selectedValue" contient l’abscisse du point. Étant donné que cette fonctionnalité sera employée à plusieurs reprises dans le code, j'ai créé une méthode qui est censée gérer l'extraction de cette valeur. Cette routine s'appelle "UserSelectValue()".

    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
                  private void UserSelectValue(){
    					userSelectedValue = false;  // Variable servant à savoir si l'utilisateur a sélectionné ou non une valeur.
    					selectedValue = null; // Variable dans laquelle est stockée la valeur sélectionnée par l'utilisateur.
     
    					final Axis<Double> xAxis = graph.getXAxis();
    					final Axis<Double> yAxis = graph.getYAxis();
     
    					final Node chartBackground = graph.lookup(".chart-plot-background");
     
    					// On actionne des eventHandler tant qu'une valeur n'a pas été sélectionné par l'utilsateur.
     
    					for (Node n: chartBackground.getParent().getChildrenUnmodifiable()) {
    						if (n != chartBackground && n != xAxis && n != yAxis) {
    							n.setMouseTransparent(true);
    						}
    					}
     
    					if (userSelectedValue == false){
     
    						chartBackground.setOnMouseEntered(new EventHandler<MouseEvent>() {
    							@Override public void handle(MouseEvent mouseEvent) {
    								System.out.println("Mouse Entered");
    								graph.setCursor(Cursor.HAND); //Change cursor to hand
    							}
    						});
     
    						chartBackground.setOnMouseClicked(new EventHandler<MouseEvent>() {
    							@Override public void handle(MouseEvent mouseEvent) {
    								System.out.println("A data have been selected by the user !");
    								selectedValue = Double.valueOf(xAxis.getValueForDisplay(mouseEvent.getX()));
    								userSelectedValue = true;
    								System.out.println("x : "+selectedValue);
     
    							}
    						});
     
    						chartBackground.setOnMouseExited(new EventHandler<MouseEvent>() {
    							@Override public void handle(MouseEvent mouseEvent) {
    								System.out.println("Mouse Exited");
    								graph.setCursor(Cursor.DEFAULT);
    							}
    						});
    					}
    				}
    Pour que cette fonctionnalité soit activable ou désactivable à la demande, j'ai créé une variable "boolean userSelectedValue" qui au moment de lancer cette fonction vaut "false". Tant que l'utilisateur n'a pas sélectionné une valeur, cette valeur n'est pas modifiée.
    Mon problème est que je ne trouve pas le moyen de désactiver cette fonctionnalité.
    En plus de cela, le programme ne semble pas attendre que l'utilisateur sélectionne une valeur pour retourner la valeur stockée dans "selectedValue". Il me retourne donc "null", ce qui génére un message d'erreur dans la fenêtre de commande dès que je clique sur le bouton.

    J'ai tenté de faire en sorte que la fonction "UserSelectValue()" retourne une valeur de type Double ou String, plutôt que d'être de type void.
    Je déclare localement une variable "final String selected = new String();", mais je ne parviens pas à lui affecter une valeur dans
    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
     
    private String UserSelectValue(){
         final String selected = new String();
         ...
         chartBackground.setOnMouseClicked(new EventHandler<MouseEvent>() {
    							@Override public void handle(MouseEvent mouseEvent) {
    								System.out.println("A data have been selected by the user !");
    								selectedValue = Double.valueOf(xAxis.getValueForDisplay(mouseEvent.getX()));
    								selected=xAxis.getValueForDisplay(mouseEvent.getX()).toString();
    								userSelectedValue = true;
    								System.out.println("x : "+selectedValue);
     
    							}
    						});
         ...
         return selected;
    }
    Eclispe me signal une erreur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    The final local variable selected cannot be assigned, since it is defined in an enclosing type
    Il semble que l’utilisation d'un if ne permet pas de désactiver cette commande. L’utilisation d'un boucle While ne fonctionne pas non plus.

    Auriez vous une idée qui me permettrait de contourner ces problèmes pour que cette fonctionnalité soit activée uniquement entre le moment ou je clique sur le bouton jusqu'au moment où une valeur est sélectionnée ?

    Comment faire en sorte que le programme attende que la valeur soit définie pour la retourner au programme ?

    Merci d'avance.

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 901
    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 901
    Billets dans le blog
    54
    Par défaut
    Bon, j'avoue que je suis un peu perdu dans les explications. Essaie de voir si ceci ne correspond pas un peu mieux a ce que tu voulais faire :

    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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    public class TrackLineChart<X extends Number, Y extends Number> extends LineChart<X, Y> {
     
        private final Region userTrackArea = new Region();
        private final Line lineUserTrackX = new Line();
        private final Line lineUserTrackY = new Line();
     
        public TrackLineChart(Axis xAxis, Axis yAxis) {
            super(xAxis, yAxis);
            userTrackXProperty().addListener(observable -> requestChartLayout());
            userTrackYProperty().addListener(observable -> requestChartLayout());
            userTrackArea.setId("userTrackArea");
            userTrackArea.mouseTransparentProperty().bind(trackUserProperty().not());
            userTrackArea.setOnMouseMoved(this::handleMouseTrackingMoved);
            userTrackArea.setOnMouseExited(this::handleTrackingMouseExit);
            userTrackArea.setOnMouseClicked(this::handleMouseTrackingClicked);
            lineUserTrackX.setId("lineUserTrackX");
            lineUserTrackX.visibleProperty().bind(trackUserProperty());
            lineUserTrackY.setId("lineUserTrackY");
            lineUserTrackY.visibleProperty().bind(trackUserProperty());
            getPlotChildren().addAll(lineUserTrackX, lineUserTrackY, userTrackArea);
        }
     
        private void handleMouseTrackingMoved(final MouseEvent mouseEvent) {
            final NumberAxis xAxis = (NumberAxis) getXAxis();
            final NumberAxis yAxis = (NumberAxis) getYAxis();
            final double mouseX = mouseEvent.getX();
            final double mouseY = mouseEvent.getY();
            final double valueX = xAxis.getValueForDisplay(mouseX).doubleValue();
            final double valueY = yAxis.getValueForDisplay(mouseY).doubleValue();
    //        System.out.printf("Mouse %f %f -> value %f (%f %f) %f (%f %f)", mouseX, mouseY,
    //                valueX, xAxis.getLowerBound(), xAxis.getUpperBound(),
    //                valueY, yAxis.getLowerBound(), yAxis.getUpperBound()).println();
            userTrackX.set(valueX);
            userTrackY.set(valueY);
        }
     
        private void handleTrackingMouseExit(final MouseEvent mouseEvent) {
            userTrackX.set(0);
            userTrackY.set(0);
        }
     
        private void handleMouseTrackingClicked(final MouseEvent mouseEvent) {
            final double mouseX = mouseEvent.getX();
            final NumberAxis xAxis = (NumberAxis) getXAxis();
            final double valueX = xAxis.getValueForDisplay(mouseX).doubleValue();
            selectionX.set(valueX);
        }
     
        ////////////////////////////////////////////////////////////////////////////
        @Override
        protected void layoutPlotChildren() {
            super.layoutPlotChildren();
            final NumberAxis xAxis = (NumberAxis) getXAxis();
            final NumberAxis yAxis = (NumberAxis) getYAxis();
            lineUserTrackX.toFront();
            lineUserTrackY.toFront();
            userTrackArea.toFront();
            final Double userTrackXObj = getUserTrackX();
            final double userTrackX = userTrackXObj == null ? 0 : userTrackXObj.doubleValue();
            final Double userTrackYObj = getUserTrackY();
            final double userTrackY = userTrackYObj == null ? 0 : userTrackYObj.doubleValue();
    //        System.out.printf("User %f %f", userTrackX, userTrackY).println();
            final double x = xAxis.getDisplayPosition(userTrackX);
            final double y = yAxis.getDisplayPosition(userTrackY);
            final double x1 = xAxis.getDisplayPosition(xAxis.getLowerBound());
            final double y1 = yAxis.getDisplayPosition(yAxis.getLowerBound());
            final double x2 = xAxis.getDisplayPosition(xAxis.getUpperBound());
            final double y2 = yAxis.getDisplayPosition(yAxis.getUpperBound());
            //
            final double screenOffset = 0.5;
            //
            layoutInArea(userTrackArea, x1, y2, x2 - x1, y1 - y2, 0, HPos.LEFT, VPos.TOP);
            //
            lineUserTrackX.setStartX(x + screenOffset);
            lineUserTrackX.setStartY(y1 + screenOffset);
            lineUserTrackX.setEndX(x + screenOffset);
            lineUserTrackX.setEndY(y2 + screenOffset);
            //
            lineUserTrackY.setStartX(x1 + screenOffset);
            lineUserTrackY.setStartY(y + screenOffset);
            lineUserTrackY.setEndX(x2);
            lineUserTrackY.setEndY(y);
        }
     
        ////////////////////////////////////////////////////////////////////////////
        private final BooleanProperty trackUser = new SimpleBooleanProperty(this, "trackUser", true);
     
        public final boolean isTrackUser() {
            return trackUser.get();
        }
     
        public final void setTrackUser(final boolean value) {
            trackUser.set(value);
        }
     
        public final BooleanProperty trackUserProperty() {
            return trackUser;
        }
     
        private final ReadOnlyDoubleWrapper userTrackX = new ReadOnlyDoubleWrapper(this, "userTrackX");
     
        public final Double getUserTrackX() {
            return userTrackX.get();
        }
     
        public final ReadOnlyDoubleProperty userTrackXProperty() {
            return userTrackX.getReadOnlyProperty();
        }
     
        private final ReadOnlyDoubleWrapper userTrackY = new ReadOnlyDoubleWrapper(this, "userTrackY");
     
        public final Double getUserTrackY() {
            return userTrackY.get();
        }
     
        public final ReadOnlyDoubleProperty userTrackYProperty() {
            return userTrackY.getReadOnlyProperty();
        }
     
        private final ReadOnlyDoubleWrapper selectionX = new ReadOnlyDoubleWrapper(this, "selectionX");
     
        public final Double getSelectionX() {
            return selectionX.get();
        }
     
        public final ReadOnlyDoubleProperty selectionXProperty() {
            return selectionX.getReadOnlyProperty();
        }
    }
    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
        public void start(Stage primaryStage) {
            final List<LineChart.Series> seriesList = new LinkedList<>();
            final int maxN = 3;
            final int minX = 0;
            final int maxX = 5;
            double minY = Double.MAX_VALUE;
            double maxY = -Double.MAX_VALUE;
            for (int n = 0 ; n <= maxN ; n++) {
                final LineChart.Series series  = new LineChart.Series<>();
                series.setName(String.format("n = %d", n));
                for (int x = minX ; x <= maxX ; x++) {
                    final double value = Math.pow(x, n);
                    minY = Math.min(minY, value);
                    maxY = Math.max(maxY, value);
                    final LineChart.Data data = new LineChart.Data(x, value);
                    series.getData().add(data);
                }
                seriesList.add(series);
            }
            final NumberAxis xAxis = new NumberAxis(minX, maxX, 1);
            xAxis.setLabel("x");
            final NumberAxis yAxis = new NumberAxis(minY, maxY, 50);
            yAxis.setLabel("y = Math.pow(x, n)");
            final TrackLineChart chart = new TrackLineChart(xAxis, yAxis);
            chart.setTitle("Fonction puissance");
            chart.getData().setAll(seriesList);
            final CheckBox trackCheck = new CheckBox("Track user");
            trackCheck.setSelected(true);
            chart.trackUserProperty().bind(trackCheck.selectedProperty());
            final ToolBar toolBar = new ToolBar();
            toolBar.getItems().add(trackCheck);
            final BorderPane root = new BorderPane();
            root.setCenter(chart);
            root.setTop(toolBar);
            Scene scene = new Scene(root, 500, 500);
            primaryStage.setTitle("Hello World!");
            primaryStage.setScene(scene);
            primaryStage.show();
            chart.selectionXProperty().addListener(observable -> System.out.printf("Selection %f", chart.getSelectionX()).println());
        }
    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 confirmé
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 48
    Par défaut
    Effectivement, à vouloir trop détailler mon explication, c'est devenu confus et difficile à comprendre.
    C'est exactement ce que je recherche.
    Il me reste plus qu'à adapter tout cela à mon programme.
    Merci beaucoup.

  4. #4
    Membre confirmé
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 48
    Par défaut
    J'ai adapté avec succès le code à mon programme. Je rencontre toutefois un problème.
    Je dois extraire du graphe une borne supérieure et une borne inférieure. Pour cela je fais appel à deux boutons différents qui sont censés extraire ces infos.
    Le programme fonctionne correctement lorsque j’extrais une première borne. La valeur choisie est alors stockée dans une variable et affichée dans un champ de texte.
    Lorsque je cherche à sélectionner une seconde borne avec le second bouton, la valeur affectée à la première borne est également modifiée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    boutonSelectedx1BaselineValueInGraph.setOnAction(new EventHandler<ActionEvent>() {
            @Override 
    	public void handle(ActionEvent event) {
            ...
                 graph.selectionXProperty().addListener(observable -> x1BaselinetextInput.setText(graph.getSelectionX().toString()));
            ...
            }
    Avez vous une idée pour contourner ce problème ?
    Merci par avance.

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 901
    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 901
    Billets dans le blog
    54
    Par défaut
    Il n'y a le code que d'un seul des deux boutons ici.
    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

  6. #6
    Membre confirmé
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 48
    Par défaut
    Le code pour le second bouton est identique, seul le nom du champ de destination change. Voici le code pour les deux boutons :
    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
    boutonSelectedx1BaselineValueInGraph.setOnAction(new EventHandler<ActionEvent>() {
            @Override 
    	public void handle(ActionEvent event) {
            ...
                 graph.selectionXProperty().addListener(observable -> x1BaselinetextInput.setText(graph.getSelectionX().toString()));
            ...
            }
    }
     
    boutonSelectedx2BaselineValueInGraph.setOnAction(new EventHandler<ActionEvent>() {
            @Override 
    	public void handle(ActionEvent event) {
            ...
                 graph.selectionXProperty().addListener(observable -> x2BaselinetextInput.setText(graph.getSelectionX().toString()));
            ...
            }
    }

Discussions similaires

  1. [XL-2010] Récupérer les coordonnées d'un point sur un graphique d'un simple clic
    Par leblesois dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 17/03/2014, 18h46
  2. Réponses: 3
    Dernier message: 13/04/2012, 11h59
  3. Trouver les coordonnées d'un point sur une surface NURBS
    Par oodini dans le forum Mathématiques
    Réponses: 2
    Dernier message: 25/05/2011, 18h35
  4. [XL-2003] Obtenir les coordonnées d'un point dans un graph en cliquant dessus
    Par triaguae dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 15/12/2010, 11h09
  5. Réponses: 4
    Dernier message: 27/11/2006, 18h06

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