JavaFX - 如何在Node周围创建可点击区域

时间:2014-06-10 01:46:01

标签: charts javafx javafx-8

我正在尝试Series点击Line,因此我可以根据用户点击的系列打开不同的选项。例如,假设我有一个这样的图表:

enter image description here

目前我有这样的事情:

    series.getNode().setOnMouseEntered(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            series.getNode().setCursor(Cursor.HAND);
        }
    });

    series.getNode().setOnMouseExited(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            series.getNode().setCursor(Cursor.DEFAULT);
        }
    });

当我通过一个系列时,光标会发生变化。它工作但有时系列太薄了你必须非常准确地点击它们,所以我想在它们周围创建一个小区域,所以点击是“近似的”,它不需要那么准确。

我怎样才能做到这一点?这个节点由2DPath组成,用于创建线条,所以我认为每条线都有自己的边界,但是如果不修改线形,就无法找到修改的方法。

1 个答案:

答案 0 :(得分:4)

在要检测鼠标事件的路径顶部覆盖另一条(几乎透明的)宽路径,并在几乎透明的路径上检测鼠标事件。

private void addGlowOnMouseOverData(LineChart<Number, Number> lineChart) {
    // make the first series in the chart glow when you mouse near it.
    Node n = lineChart.lookup(".chart-series-line.series0");
    if (n != null && n instanceof Path) {
        final Path path = (Path) n;
        final Glow glow = new Glow(0.8);

        final Path mousingPath = new Path();
        mousingPath.setStrokeWidth(24);
        mousingPath.setStroke(Color.rgb(255, 255, 255, 0.01));
        Bindings.bindContent(mousingPath.getElements(), path.getElements());
        ((Group) path.getParent()).getChildren().add(mousingPath);

        mousingPath.setOnMouseEntered(e -> path.setEffect(glow));
        mousingPath.setOnMouseExited(e -> path.setEffect(null));
    }
}

可执行样本

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.*;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.effect.Glow;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Path;
import javafx.stage.Stage;

public class LineChartMouser extends Application {
    @SuppressWarnings("unchecked")
    @Override
    public void start(Stage stage) {
        // initialize data
        ObservableList<XYChart.Data> data = FXCollections.observableArrayList(
                new XYChart.Data(1, 23), new XYChart.Data(2, 14), new XYChart.Data(3, 15), new XYChart.Data(4, 24), new XYChart.Data(5, 34), new XYChart.Data(6, 36), new XYChart.Data(7, 22), new XYChart.Data(8, 45), new XYChart.Data(9, 43), new XYChart.Data(10, 17), new XYChart.Data(11, 29), new XYChart.Data(12, 25)
        );

        // create chart
        final LineChart lineChart = createChart(data);
        StackPane layout = new StackPane(lineChart);

        // show the scene.
        Scene scene = new Scene(layout, 800, 600);
        stage.setScene(scene);
        stage.show();

        // add a glow when you mouse over the lines in the line chart so that you can see that they are chosen.
        addGlowOnMouseOverData(lineChart);
    }

    private void addGlowOnMouseOverData(LineChart<Number, Number> lineChart) {
        // make the first series in the chart glow when you mouse near it.
        Node n = lineChart.lookup(".chart-series-line.series0");
        if (n != null && n instanceof Path) {
            final Path path = (Path) n;
            final Glow glow = new Glow(0.8);

            final Path mousingPath = new Path();
            mousingPath.setStrokeWidth(24);
            mousingPath.setStroke(Color.rgb(255, 255, 255, 0.01));
            Bindings.bindContent(mousingPath.getElements(), path.getElements());
            ((Group) path.getParent()).getChildren().add(mousingPath);

            mousingPath.setOnMouseEntered(e -> path.setEffect(glow));
            mousingPath.setOnMouseExited(e -> path.setEffect(null));
        }
    }

    private LineChart createChart(ObservableList<XYChart.Data> data) {
        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();
        xAxis.setLabel("Number of Month");
        final LineChart lineChart = new LineChart<>(xAxis, yAxis);
        lineChart.setTitle("Stock Monitoring, 2010");
        XYChart.Series series = new XYChart.Series(data);
        series.setName("My portfolio");
        lineChart.getData().add(series);
        lineChart.setCreateSymbols(false);
        lineChart.setLegendVisible(false);

        return lineChart;
    }

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