简体   繁体   English

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

[英]JavaFX - How to create a clickable area around Node

I am trying to make the Series in a Line clickable so I can open different options based on the series the user clicked. 我正在尝试使“ LineSeries可单击,以便根据用户单击的系列打开不同的选项。 For example, suppose I have a chart like this: 例如,假设我有一个像这样的图表:

在此处输入图片说明

Currently I have something like this: 目前我有这样的事情:

    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);
        }
    });

So cursor changes when I pass through a series. 因此,当我通过一系列游标时,光标会发生变化。 It is working but sometimes series are too thin and you have to be very accurate to click on them, so I was thinking of creating a small area around them so the click is "approximated" and it doesn't need to be that accurate. 它可以工作,但是有时序列太细,您必须非常准确才能单击它们,因此我考虑在它们周围创建一个较小的区域,这样单击就可以“近似”,并且不需要那么精确。

How can I achieve this? 我该如何实现? This nodes consists of a 2DPath to create the lines so I think every line has it's own bounds but can't figure out a way to modify without modifying line shape. 该节点由2DPath组成,用于创建线,因此我认为每条线都有其自己的边界,但无法找出一种无需修改线形即可进行修改的方法。

Layer another (almost transparent) wide path over the top of the path you want to detect mouse events on and instead detect mouse events on the almost transparent path. 在要在其上检测鼠标事件,而在几乎透明的路径上检测鼠标事件的路径的顶部,放置另一个(几乎透明)的宽路径。

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));
    }
}

Executable Sample 可执行样本

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM