【问题标题】:JavaFX: set ClickListener on nodes of a LineChartJavaFX:在折线图的节点上设置单击侦听器
【发布时间】:2018-01-28 15:56:14
【问题描述】:

我有一个 JavaFX 应用程序,它首先计算一些数据,然后在 LineChart 上添加数据点。我想在节点上添加一个 ClickListener,如果用户单击图表上的任何节点,相应的值将出现在 TableView 或其他内容中。但我无法检索节点的值。

代码如下:

lineChart.getData().add(series);
series.getNode().setOnMouseClicked(nodeClicked);

EventListener 的代码:

EventHandler<MouseEvent> nodeClicked = new EventHandler<MouseEvent>(){

        @Override
        public void handle(MouseEvent event) {
            System.out.println("clicked");
        }
};

我也尝试在 LineChart 上设置监听器,但在事件对象中找不到相应的节点信息,如值等。

提前谢谢你,最好的问候

【问题讨论】:

  • 这应该为 series 的节点添加一个监听器(即构成折线图的线)。这是您想要的,还是您想要在节点上为各个数据点设置一个侦听器?
  • @James_D 没错,我想在每个数据点上都有一个监听器,所以如果你点击图表上的一个点,你应该得到那个数据点的值。
  • 因此您需要从实际的XYChart.Data 对象中获取每个节点,并为这些对象添加监听器。
  • @James_D 但是怎么做呢?首先,我使用 x 和 y 的 2 个值创建一个 XYChart.Data 对象。之后我将它们添加到系列中,最后将系列添加到 LineChart。如果我在直接声明数据对象后尝试设置监听器,我会得到一个 NullPointerException。
  • 好吧,没有人能告诉你他们看不到的代码有什么问题。我最好的猜测是,您在将数据添加到图表之前从数据中检索节点(在将数据添加到图表之前不会创建节点)。但是大概你可以从堆栈跟踪中找出实际上是什么是空的......?

标签: java user-interface javafx linechart


【解决方案1】:

您似乎正在将处理程序添加到与数据系列关联的节点。折线图中的这个节点就是折线本身,因此当您单击折线时应该会看到控制台输出。

要让侦听器自己响应对数据点的点击,您需要将侦听器添加到与各个 XYChart.Data 实例关联的节点。

请注意,这些节点仅在将数据添加到系列并且将系列添加到图表后创建;所以你必须小心,只有在这些发生后才添加事件处理程序。

这是一个 SSCCE:

import java.util.Random;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;

public class LineChartWithEventHandlers extends Application {

    @Override
    public void start(Stage primaryStage) {

        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
        Series<Number, Number> series = new Series<>();
        series.setName("Data");

        chart.getData().add(series);

        // handler for clicking on line:
        series.getNode().setOnMouseClicked(e -> System.out.println("Click on series"));

        Random rng = new Random();
        for (int x = 0 ; x <= 20 ; x++) {
            Data<Number, Number> data = new Data<>(x, rng.nextInt(100));
            series.getData().add(data);

            // handler for clicking on data point:
            data.getNode().setOnMouseClicked(e -> 
                System.out.printf("Click on data [%d, %d]%n", data.getXValue(), data.getYValue()));
        }

        Scene scene = new Scene(chart);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

点击线条后的屏幕截图,两个不同的数据点,再次点击线条:

【讨论】:

  • 像魅力一样工作。非常感谢你。你是对的,我在将系列添加到图表之前添加了监听器。
  • @serij 是的:见答案的第三段。
  • 本质上,它为每个图表符号创建一个单独的处理程序,其中包含相应Data 项目的引用。当点不是很多时,这很好用。但是,当一个图表包含几个系列,每个系列都有数千个点时,它可能会变得过于笨拙。我试图在所有节点共享的单个公共处理程序中从鼠标事件目标(即StackPane)获取数据项的引用,但没有成功。有没有办法通过其各自的节点访问数据?
猜你喜欢
  • 2014-03-14
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 2013-12-17
相关资源
最近更新 更多