JavaFX: Есть ли способ для оси Y быть положительным вверх с началом координат внизу слева? - PullRequest
2 голосов
/ 17 февраля 2020

Система координат JavaFX dr aws Y координирует от вершины экрана, и положительна вниз. Я бы хотел, чтобы он был положительным вверх и начинался с нижней части экрана.

Необходимо выполнить перевод, а текстовые узлы нужно перевернуть.

И, надеюсь, с этим нарисованный прямоугольник будет расположен «естественным» образом, как мы это делаем в математическом классе. С его левым нижним краем в начале координат, расширяющимся к верхнему правому.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class FlippedExampleChart extends Application {

    private LineChart<Number, Number> chart;

    @Override
    public void start(Stage primaryStage) throws Exception {
        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();

        // Flip the axis
        yAxis.setScaleY(-1);

        // TODO How to translate to bottom of screen.
        // TODO How to flip the text nodes.

        this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
            @Override
            public void layoutPlotChildren() {
                super.layoutPlotChildren();

                double height = yAxis.getDisplayPosition(100);

                Rectangle r = new Rectangle(0, 0, 50, height);
                r.setFill(Color.GREEN);
                getPlotChildren().addAll(r);
            }
        };
        this.chart.setAnimated(false);

        VBox vbox = new VBox(this.chart);

        Scene scene = new Scene(vbox, 400, 200);
        primaryStage.setScene(scene);
        primaryStage.setHeight(600);
        primaryStage.setWidth(400);
        primaryStage.show();
    }

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

enter image description here

1 Ответ

6 голосов
/ 18 февраля 2020

Я предполагаю, что цель состоит в том, чтобы нарисовать фигуру, используя систему координат, определенную осями диаграммы.

Самый простой способ - это преобразовать форму вместо оси. Для этого вы можете создать служебный метод:

private Transform chartDisplayTransform(NumberAxis xAxis, NumberAxis yAxis) {
    return new Affine(
            xAxis.getScale(), 0, xAxis.getDisplayPosition(0),
            0, yAxis.getScale(), yAxis.getDisplayPosition(0)
    );
}

Еще одно замечание о вашем коде: метод layoutPlotChildren() не обязательно удаляет узлы, поэтому вы можете добавить больше прямоугольников, чем ожидаете, с помощью код вы разместили.

Вот версия вашего кода, которая использует этот метод (и гарантирует, что прямоугольник добавляется только один раз).

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;

public class FlippedExampleChart extends Application {

    private LineChart<Number, Number> chart;

    @Override
    public void start(Stage primaryStage) throws Exception {
        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();

        // Flip the axis
        // yAxis.setScaleY(-1);

        Rectangle r = new Rectangle(0, 0, 50, 100);
        r.setFill(Color.GREEN);

        this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
            @Override
            public void layoutPlotChildren() {
                super.layoutPlotChildren();
                r.getTransforms().setAll(chartDisplayTransform(xAxis, yAxis));
                // note nodes don't get removed from the plot children, and this method may be
                // called often:
                if (!getPlotChildren().contains(r)) {
                    getPlotChildren().add(r);
                }
            }
        };
        this.chart.setAnimated(false);

        VBox vbox = new VBox(this.chart);

        Scene scene = new Scene(vbox, 400, 200);
        primaryStage.setScene(scene);
        primaryStage.setHeight(600);
        primaryStage.setWidth(400);
        primaryStage.show();
    }

    private Transform chartDisplayTransform(NumberAxis xAxis, NumberAxis yAxis) {
        return new Affine(xAxis.getScale(), 0, xAxis.getDisplayPosition(0), 0, yAxis.getScale(),
                yAxis.getDisplayPosition(0));
    }

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

И результат:

enter image description here

Если у вас есть несколько узлов для обработки таким образом, стратегия состоит в том, чтобы добавить их Group и примените преобразование к Group:

@Override
public void start(Stage primaryStage) throws Exception {
    final NumberAxis xAxis = new NumberAxis();
    final NumberAxis yAxis = new NumberAxis();

    Group extraNodes = new Group();

    this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
        @Override
        public void layoutPlotChildren() {
            super.layoutPlotChildren();
            Rectangle r1 = new Rectangle(0, 0, 50, 100);
            r1.setFill(Color.GREEN);
            Rectangle r2 = new Rectangle(70, 0, 30, 20);
            r2.setFill(Color.AQUAMARINE);
            extraNodes.getChildren().setAll(r1, r2);
            extraNodes.getTransforms().setAll(chartDisplayTransform(xAxis, yAxis));
            // note nodes don't get removed from the plot children, and this method may be
            // called often:
            if (!getPlotChildren().contains(extraNodes)) {
                getPlotChildren().add(extraNodes);
            }
        }
    };
    this.chart.setAnimated(false);

    VBox vbox = new VBox(this.chart);

    Scene scene = new Scene(vbox, 400, 200);
    primaryStage.setScene(scene);
    primaryStage.setHeight(600);
    primaryStage.setWidth(400);
    primaryStage.show();
}

Также см. этот связанный вопрос

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...