在鼠标单击事件中重置散点图的节点颜色

Reset scatter chart's node color in a mouse-clicked event

我编写了这段创建散点图的代码,并允许我在 click/select 时更改图中节点的颜色。

 package com.jpc.javafx.charttest;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class CreateChart extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {  

//-------Create Chart--------------
      NumberAxis xAxis = new NumberAxis();
      NumberAxis yAxis = new NumberAxis();
      
      XYChart.Series<Number,Number> dataSeries1 = new XYChart.Series();
      ScatterChart chart = new ScatterChart(xAxis,yAxis); 
      
      dataSeries1.getData().add(new XYChart.Data( 1, 567));
      dataSeries1.getData().add(new XYChart.Data( 5, 612));
      dataSeries1.getData().add(new XYChart.Data(10, 800));

      chart.getData().add(dataSeries1);

   //-----Select node and change color -----

      for(final XYChart.Data<Number,Number> data : dataSeries1.getData()) { 
          data.getNode().setOnMouseClicked(e-> {
          //dataSeries1.getNode().lookup(".chart-symbol").setStyle("-fx-background-color: red"); that does not work 
          data.getNode().setStyle("-fx-background-color: blue" );
      });
      }

      VBox vbox = new VBox(chart);

      Scene scene = new Scene(vbox, 400, 200);

      primaryStage.setScene(scene);
      primaryStage.setHeight(300);
      primaryStage.setWidth(1200);

      primaryStage.show();
  }
  
    public static void main(String[] args) {
        Application.launch(args);
    }
}

问题是,当我 select 另一个点时,前一个点保持蓝色。因此,在更改 selected 点的颜色之前,我需要将所有节点重置为默认颜色。 我试着添加这个:

dataSeries1.getNode().lookup(".chart-symbol").setStyle("-fx-background-color: red");

但我得到:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException

您可以做的一件事是遍历数据并更改单击的颜色,并将所有其他设置为 null

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class CreateChart extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {  

//-------Create Chart--------------
      NumberAxis xAxis = new NumberAxis();
      NumberAxis yAxis = new NumberAxis();
      
      XYChart.Series<Number,Number> dataSeries1 = new XYChart.Series();
      ScatterChart chart = new ScatterChart(xAxis,yAxis); 
      
      dataSeries1.getData().add(new XYChart.Data( 1, 567));
      dataSeries1.getData().add(new XYChart.Data( 5, 612));
      dataSeries1.getData().add(new XYChart.Data(10, 800));

      chart.getData().add(dataSeries1);

   //-----Select node and change color -----

      for(final XYChart.Data<Number,Number> data : dataSeries1.getData()) { 
          data.getNode().setOnMouseClicked(e-> {
          for(final XYChart.Data<Number,Number> data2 : dataSeries1.getData()) {
              if(data == data2)
              {
                    data2.getNode().setStyle("-fx-background-color: blue" );
              }
              else
              {
                  data2.getNode().setStyle(null);
              }
          }
      });
      }

      VBox vbox = new VBox(chart);

      Scene scene = new Scene(vbox, 400, 200);

      primaryStage.setScene(scene);
      primaryStage.setHeight(300);
      primaryStage.setWidth(1200);

      primaryStage.show();
  }
  
    public static void main(String[] args) {
        Application.launch(args);
    }
}

总结您的要求:

  • chart-symbol 的视觉效果 属性 应在用户交互时标记
  • 应该只有一个这样的标记符号

听起来像是一种选择机制——开箱即用的图表符号不支持这种机制,应用程序代码必须处理它。任务是

  • 跟踪(最后)选定的交易品种
  • 保证在任何时候都只选择一个品种
  • 根据需要保持 un/selected 的视觉状态

最简单的逻辑实现(前两个项目符号)是保留对当前所选内容的引用并在用户交互时更新它。后者的合适工具是伪类:可以在 css 和 de/activated 中与逻辑一起定义。

代码片段(插入到您的示例中)

// Pseudo-class
private PseudoClass selected = PseudoClass.getPseudoClass("selected");
// selected logic
private Node selectedSymbol;

protected void setSelectedSymbol(Node symbol) {
    if (selectedSymbol != null) {
        selectedSymbol.pseudoClassStateChanged(selected, false);
    }
    selectedSymbol = symbol;
    if (selectedSymbol != null) {
        selectedSymbol.pseudoClassStateChanged(selected, true);
    }
}

// event handler on every symbol
data.getNode().setOnXX(e -> setSelectedSymbol(data.getNode()));

css 示例,通过 style-sheet f.i.:

加载
.chart-symbol:selected {
   -fx-background-color: blue;
}