Javafx 在StackPane中设置在轴上按下鼠标的操作。请

Javafx 在StackPane中设置在轴上按下鼠标的操作。请,javafx,javafx-2,action,linechart,stackpanel,Javafx,Javafx 2,Action,Linechart,Stackpanel,我有一个带有图表()的StackPane。我想为yAxis设定一些动作。GUI中没有结果,但对于baseChart(不在StackPane中)来说效果很好。如何设置轴的动作 MCVE 带有JFrame的mainclass: import javafx.application.Application; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.scene.Group;

我有一个带有图表()的
StackPane
。我想为yAxis设定一些动作。GUI中没有结果,但对于baseChart(不在
StackPane
中)来说效果很好。如何设置轴的动作

MCVE

带有JFrame的mainclass:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.function.Function;

public abstract class mainClass extends Application {
    public static final int X_NUMBER = 20;
    static StackChart chart;
  
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAndShowGUI();
            }
        });
    }

    private static void initAndShowGUI() {
        // This method is invoked on Swing thread
        JFrame frame = new JFrame("FX");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setVisible(true);
        frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(), (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());
    
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX(fxPanel);
            }
        });
    }

    private static void initFX(JFXPanel fxPanel) {
            // This method is invoked on JavaFX thread
            Scene scene = createScene();
            fxPanel.setScene(scene);
        }
    private static Scene createScene()    {
        Group root = new Group();
        Scene scene = new Scene(root, 1024, 600);

        BorderPane borderPane = new BorderPane();

        NumberAxis xAxis = new NumberAxis();
        NumberAxis yAxis = new NumberAxis();

        yAxis.setLabel("Scale 1");
        LineChart baseChart = new LineChart(xAxis, yAxis);
        baseChart.getData().add(prepareSeries("Serie 1", (x) -> (double) x));

        chart = new StackChart(baseChart, Color.RED);
        chart.addSeries(prepareSeries("Serie 2", (x) -> (double) -2*x * x), Color.BLUE);
            
        borderPane.setCenter(chart);

        borderPane.setPrefSize(800, 600);
        borderPane.setBottom(chart.getLegend());

        root.getChildren().add(borderPane);

        return scene;
    }

    private static XYChart.Series<Number, Number> prepareSeries(String name, Function<Integer, Double> function) {
        XYChart.Series<Number, Number> series = new XYChart.Series<>();
        series.setName(name);
        for (int i = 0; i < X_NUMBER; i++) {
            series.getData().add(new XYChart.Data<>(i, function.apply(i)));
        }
        return series;
    }

    
}
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.embed.swing.JFXPanel;
导入javafx.scene.Group;
导入javafx.scene.scene;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.paint.Color;
导入javax.swing.*;
导入java.awt.*;
导入java.awt.event.KeyEvent;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.util.function.function;
公共抽象类mainClass扩展了应用程序{
公共静态最终整数X_数=20;
静态堆栈图;
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
initAndShowGUI();
}
});
}
私有静态void initAndShowGUI(){
//此方法在Swing线程上调用
JFrame=新JFrame(“FX”);
最终JFXPanel fxPanel=新JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);
frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(),(int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
initFX(fxPanel);
}
});
}
私有静态void initFX(JFXPanel fxPanel){
//此方法在JavaFX线程上调用
Scene-Scene=createScene();
fxPanel.setScene(场景);
}
私有静态场景CreateSecene(){
组根=新组();
场景=新场景(根,1024600);
BorderPane BorderPane=新的BorderPane();
NumberAxis xAxis=新NumberAxis();
NumberAxis yAxis=新的NumberAxis();
yAxis.setLabel(“比例1”);
线形图基线图=新线形图(xAxis,yAxis);
baseChart.getData().add(prepareSeries(“serie1”,(x)->(double)x));
图表=新的堆叠图表(底图,颜色为红色);
图表添加系列(准备系列(“系列2”,(x)->(双色)-2*x*x),颜色为蓝色);
边框窗格。设置中心(图表);
borderPane.setPrefSize(800600);
setBottom(chart.getLegend());
root.getChildren().add(边框窗格);
返回场景;
}
私有静态XYChart.Series准备序列(字符串名称、函数){
XYChart.Series系列=新的XYChart.Series();
series.setName(name);
对于(int i=0;i
堆栈图表类:

import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;

public class StackChart extends StackPane {

    private final LineChart baseChart;
    private final ObservableList<LineChart> backCharts = FXCollections.observableArrayList();

    private final double yAxisWidth = 60;
    private final AnchorPane details;

    private final double yAxisSeparation = 20;
    private double strokeWidth = 0.3;

    public int _formatType = 1;

    public StackChart(LineChart baseChart, Color lineColor) {
        this(baseChart, lineColor, null);
    }

    public StackChart(LineChart baseChart, Color lineColor, Double strokeWidth) {
        if (strokeWidth != null) {
            this.strokeWidth = strokeWidth;
        }
        this.baseChart = baseChart;
        baseChart.setCreateSymbols(false);
        baseChart.setLegendVisible(false);
        baseChart.getXAxis().setAutoRanging(false);
        baseChart.getXAxis().setAnimated(false);
        baseChart.getXAxis().setStyle("-fx-font-size:" + 18);
        baseChart.getYAxis().setAnimated(false);
        baseChart.getYAxis().setStyle("-fx-font-size:" + 18);

        setStyle(baseChart, lineColor);
        setFixedAxisWidth(baseChart);
        setAlignment(Pos.CENTER_LEFT);

        backCharts.addListener((Observable observable) -> rebuildChart());

        details = new AnchorPane();
        bindMouseEvents(baseChart, this.strokeWidth);

        rebuildChart();
    }

    private void bindMouseEvents(LineChart baseChart, Double strokeWidth) {

        getChildren().add(details);

        details.prefHeightProperty().bind(heightProperty());
        details.prefWidthProperty().bind(widthProperty());
        details.setMouseTransparent(true);

        setOnMouseMoved(null);
        setMouseTransparent(false);

        final Axis xAxis = baseChart.getXAxis();
        final Axis yAxis = baseChart.getYAxis();

        final Line xLine = new Line();
        final Line yLine = new Line();
        yLine.setFill(Color.GRAY);
        xLine.setFill(Color.GRAY);
        yLine.setStrokeWidth(strokeWidth/2);
        xLine.setStrokeWidth(strokeWidth/2);
        xLine.setVisible(false);
        yLine.setVisible(false);

        final Node chartBackground = baseChart.lookup(".chart-plot-background");
        for (Node n: chartBackground.getParent().getChildrenUnmodifiable()) {
            if (n != chartBackground && n != xAxis && n != yAxis) {
                n.setMouseTransparent(true);
            }
        }
        chartBackground.setCursor(Cursor.CROSSHAIR);
        chartBackground.setOnMouseEntered((event) -> {
            chartBackground.getOnMouseMoved().handle(event);
            xLine.setVisible(true);
            yLine.setVisible(true);
            details.getChildren().addAll(xLine, yLine);
        });
        chartBackground.setOnMouseExited((event) -> {

            xLine.setVisible(false);
            yLine.setVisible(false);
            details.getChildren().removeAll(xLine, yLine);
        });
        chartBackground.setOnMouseMoved(event -> {
            double x = event.getX() + chartBackground.getLayoutX();
            double y = event.getY() + chartBackground.getLayoutY();

            xLine.setStartX(65);
            xLine.setEndX(details.getWidth()-10);
            xLine.setStartY(y+5);
            xLine.setEndY(y+5);

            yLine.setStartX(x+5);
            yLine.setEndX(x+5);
            yLine.setStartY(12);
            yLine.setEndY(details.getHeight()-28);
        });

    }

    private void setFixedAxisWidth(LineChart chart) {
        chart.getYAxis().setPrefWidth(yAxisWidth);
        chart.getYAxis().setMaxWidth(yAxisWidth);
    }

    private void rebuildChart() {
        getChildren().clear();

        getChildren().add(resizeBaseChart(baseChart));
        for (LineChart lineChart : backCharts) {
            getChildren().add(resizeBackgroundChart(lineChart));
        }
        getChildren().add(details);
    }

    private Node resizeBaseChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));

        return lineChart;
    }

    private Node resizeBackgroundChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());
        hBox.setMouseTransparent(true);

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));

        lineChart.translateXProperty().bind(baseChart.getYAxis().widthProperty());
        lineChart.getYAxis().setTranslateX((yAxisWidth + yAxisSeparation) * backCharts.indexOf(lineChart));

        return hBox;
    }

    public void addSeries(XYChart.Series series, Color lineColor) {
        NumberAxis yAxis = new NumberAxis();
        NumberAxis xAxis = new NumberAxis();

        // xAxis
        xAxis.setAutoRanging(false);
        xAxis.setVisible(false);
        xAxis.setOpacity(0.0);
        xAxis.lowerBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).lowerBoundProperty());
        xAxis.upperBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).upperBoundProperty());
        xAxis.tickUnitProperty().bind(((NumberAxis) baseChart.getXAxis()).tickUnitProperty());

        // yAxis
        yAxis.setSide(Side.RIGHT);
        yAxis.setLabel(series.getName());

        // create chart
        LineChart lineChart = new LineChart(xAxis, yAxis);
        lineChart.setAnimated(false);
        lineChart.setLegendVisible(false);
        lineChart.getData().add(series);

//HERE
        for (LineChart ch : backCharts) {
            ch.getYAxis().setCursor(Cursor.CLOSED_HAND);
            ch.getYAxis().setOnMousePressed(event -> {
                ch.getYAxis().setLabel("123");
            });
        }

        styleBackChart(lineChart, lineColor);
        setFixedAxisWidth(lineChart);

        backCharts.add(lineChart);
    }

    private void styleBackChart(LineChart lineChart, Color lineColor) {
        setStyle(lineChart, lineColor);

        Node contentBackground = lineChart.lookup(".chart-content").lookup(".chart-plot-background");
        contentBackground.setStyle("-fx-background-color: transparent;");

        lineChart.setVerticalZeroLineVisible(false);
        lineChart.setHorizontalZeroLineVisible(false);
        lineChart.setVerticalGridLinesVisible(false);
        lineChart.setHorizontalGridLinesVisible(false);
        lineChart.setCreateSymbols(false);
        lineChart.getXAxis().setStyle("-fx-font-size:" + 18);
        lineChart.getYAxis().setStyle("-fx-font-size:" + 18);
    }

    private String toRGBCode(Color color) {
        return String.format("#%02X%02X%02X",
                (int) (color.getRed() * 255),
                (int) (color.getGreen() * 255),
                (int) (color.getBlue() * 255));
    }

    private void setStyle(LineChart chart, Color lineColor) {
        chart.getYAxis().lookup(".axis-label").setStyle("-fx-text-fill: " + toRGBCode(lineColor) + "; -fx-font-size: 24;");
        Node seriesLine = chart.lookup(".chart-series-line");
        seriesLine.setStyle("-fx-stroke: " + toRGBCode(lineColor) + "; -fx-stroke-width: " + strokeWidth + ";");
    }

    public Node getLegend() {
        HBox hbox = new HBox();

        final CheckBox baseChartCheckBox = new CheckBox(baseChart.getYAxis().getLabel());
        baseChartCheckBox.setSelected(true);
        baseChartCheckBox.setDisable(true);
        baseChartCheckBox.getStyleClass().add("readonly-checkbox");
        baseChartCheckBox.setOnAction(event -> baseChartCheckBox.setSelected(true));
        hbox.getChildren().add(baseChartCheckBox);

        for (final LineChart lineChart : backCharts) {
            CheckBox checkBox = new CheckBox(lineChart.getYAxis().getLabel());
            checkBox.setSelected(true);
            checkBox.setOnAction(event -> {
                if (backCharts.contains(lineChart)) {
                    backCharts.remove(lineChart);
                } else {
                    backCharts.add(lineChart);
                }
            });
            hbox.getChildren().add(checkBox);
        }

        hbox.setAlignment(Pos.CENTER);
        hbox.setSpacing(20);
        hbox.setStyle("-fx-padding: 0 10 20 10");

        return hbox;
    }

    public int is_formatType() {
        return _formatType;
    }

    public void set_formatType(int formatType) {
        this._formatType = formatType;
        this.requestLayout();
    }
}
导入javafx.beans.Observable;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.geometry.Pos;
导入javafx.geometry.Side;
导入javafx.scene.Cursor;
导入javafx.scene.Node;
导入javafx.scene.chart.Axis;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart;
导入javafx.scene.control.CheckBox;
导入javafx.scene.layout.ancorpane;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Line;
公共类StackChart扩展了StackPane{
私人最终线形图基础图;
私有最终ObservableList backCharts=FXCollections.observableArrayList();
私人最终双yAxisWidth=60;
私人最终主播详细信息;
私人最终双倍分离=20;
专用双冲程宽度=0.3;
公共int _formatType=1;
公共堆叠图(线条图底图、彩色线条图){
这(基线图、线颜色、空);
}
公共堆栈图(折线图底图、彩色折线图、双冲程宽度){
如果(冲程宽度!=null){
this.strokeWidth=strokeWidth;
}
this.baseChart=baseChart;
baseChart.SetCreateSymbles(假);
baseChart.setLegendVisible(假);
baseChart.getXAxis().setAutoRanging(false);
baseChart.getXAxis().setAnimated(false);
baseChart.getXAxis().setStyle(“-fx字体大小:”+18);
baseChart.getYAxis().setAnimated(false);
baseChart.getYAxis().setStyle(“-fx字体大小:”+18);
设置样式(基线图、线条颜色);
设置固定轴宽度(基线图);
设置对齐(位置中心左);
addListener((可观察到的)->rebuildChart());
细节=新的锚烷();
bindMouseEvents(基线图,此.strokeWidth);
重建哈特();
}
专用void bindMouseEvents(折线图底图,双冲程宽度){
getChildren().add(详细信息);
details.prefHeightProperty().bind(heightProperty());
details.prefWidthProperty().bind(widthProperty());
详细信息。setMouseTransparent(true);
setOnMouseMoved(空);
setMouseTransparent(假);
最终轴xAxis=baseChart.getXAxis();
最终轴yAxis=baseChart.getYAxis();
最后一行xLine=新行();
最后一行yLine=新行();
yLine.setFill(颜色:灰色);
xLine.setFill(颜色:灰色);
yLine.设置行程宽度(行程宽度/2);
xLine.设置行程宽度(行程宽度/2);
xLine.setVisible(假);
yLine.setVisible(false);
最终节点chartBackground=baseChart.lookup(“.chart-plot-background”);
对于(节点n:chartBackground.getParent().getChildrenUnmodifiable()){
如果(n=