如何在JavaFX 8中使用AnchorPane覆盖图表图?

Vel*_* Jr 7 java javafx

这是这个问题的延续.

我试图用AnchorPane覆盖图表情节,我称之为缓冲区.

在此输入图像描述

这是一个代码示例.

package launcher;

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        NumberAxis numberAxis = new NumberAxis();
        LineChart<Number, Number> chart = new LineChart<>(numberAxis, new NumberAxis());
        chart.getYAxis().setSide(Side.RIGHT);

        AnchorPane buffer = new AnchorPane();
        buffer.setStyle("-fx-background-color: gray;" +
                "-fx-opacity: 0.5");

        AnchorPane anchorPane = new AnchorPane();
        AnchorPane.setTopAnchor(chart, 0.0);
        AnchorPane.setRightAnchor(chart, 0.0);
        AnchorPane.setBottomAnchor(chart, 0.0);
        AnchorPane.setLeftAnchor(chart, 0.0);

        anchorPane.getChildren().addAll(chart, buffer);

        Scene scene = new Scene(anchorPane);
        primaryStage.setScene(scene);
        primaryStage.setMaximized(true);

        primaryStage.show();

        resetBuffer(chart, buffer, anchorPane);

        anchorPane.widthProperty().addListener((observable, oldValue, newValue) -> {

            resetBuffer(chart, buffer, anchorPane);
        });
    }

    private void resetBuffer(LineChart<Number, Number> chart, AnchorPane buffer,
                             AnchorPane anchorPane) {
        Node chartPlot = chart.lookup(".chart-plot-background");

        Bounds bounds = anchorPane.sceneToLocal(
                chartPlot.localToScene(chartPlot.getBoundsInLocal()));

        buffer.setPrefWidth(bounds.getWidth());
        buffer.setPrefHeight(bounds.getHeight());

        AnchorPane.setLeftAnchor(buffer, bounds.getMinX());
        AnchorPane.setTopAnchor(buffer, bounds.getMinY());
    }
}
Run Code Online (Sandbox Code Playgroud)

一切正常,直到我调整舞台.当我调整大小时,AnchorPane(缓冲区)没有正确覆盖图表.即它不适合大小.

如何解决或以正确的方式做到这一点?

Sar*_*cht 2

希望这能解决这个问题:

第一个解决方案:

    double sideSizeWidth = (anchorPane.getWidth()-bounds.getWidth());
    double sideSizeHeight= (anchorPane.getHeight()-bounds.getHeight());

    buffer.prefWidthProperty().bind(Bindings.add(
            chart.widthProperty(),
            -sideSizeWidth
    ));
    buffer.prefHeightProperty().bind(Bindings.add(
            chart.heightProperty(),
            -sideSizeHeight
    ));
Run Code Online (Sandbox Code Playgroud)

(它需要在resetBuffer并且只需要在开始时调用一次,当然之后primaryStage.show()

第二种解决方案:

 scene.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                double dif =oldValue.doubleValue()-newValue.doubleValue();
                buffer.setPrefWidth(buffer.getWidth()-(dif));
            }
        });
        scene.heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                double dif =oldValue.doubleValue()-newValue.doubleValue();
                buffer.setPrefHeight(buffer.getHeight()-(dif));
            }
        });
Run Code Online (Sandbox Code Playgroud)

它基于这样的事实:宽度和高度在轴标签和图例中是永久的,因此我们只需要计算scene应用到的尺寸上的差异buffer

全部代码:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        NumberAxis numberAxis = new NumberAxis();
        LineChart<Number, Number> chart = new LineChart<>(numberAxis, new NumberAxis());
        chart.getYAxis().setSide(Side.RIGHT);

        AnchorPane buffer = new AnchorPane();
        buffer.setStyle("-fx-background-color: gray;" +
                "-fx-opacity: 0.5");

        AnchorPane anchorPane = new AnchorPane();
        AnchorPane.setTopAnchor(chart, 0.0);
        AnchorPane.setRightAnchor(chart, 0.0);
        AnchorPane.setBottomAnchor(chart, 0.0);
        AnchorPane.setLeftAnchor(chart, 0.0);

        anchorPane.getChildren().addAll(chart, buffer);

        Scene scene = new Scene(anchorPane);
        primaryStage.setScene(scene);
        primaryStage.setMaximized(true);

        primaryStage.show();

        resetBuffer(chart, buffer, anchorPane,scene);



    }

    private void resetBuffer(LineChart<Number, Number> chart, AnchorPane buffer,
                             AnchorPane anchorPane,Scene scene) {
        Node chartPlot = chart.lookup(".chart-plot-background");

        Bounds bounds = anchorPane.sceneToLocal(
                chartPlot.localToScene(chartPlot.getBoundsInLocal()));

        buffer.setPrefWidth(bounds.getWidth());
        buffer.setPrefHeight(bounds.getHeight());

        AnchorPane.setLeftAnchor(buffer, bounds.getMinX());
        AnchorPane.setTopAnchor(buffer, bounds.getMinY());

        scene.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                double dif =oldValue.doubleValue()-newValue.doubleValue();
                buffer.setPrefWidth(buffer.getWidth()-(dif));
            }
        });
        scene.heightProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                double dif =oldValue.doubleValue()-newValue.doubleValue();
                buffer.setPrefHeight(buffer.getHeight()-(dif));
            }
        });

    }
}
Run Code Online (Sandbox Code Playgroud)