JavaFx увеличивать и уменьшать масштаб относительно указателя мыши - PullRequest
0 голосов
/ 23 марта 2020

Я работаю над проектом JavaFx (Olympics Archery), в котором мне нужно выполнить операции масштабирования на панели. Я хочу выполнить операцию масштабирования относительно указателя мыши, поэтому я скопировал этот код из this для достижения желаемого результата. Но почему-то это происходит не так, как я хотел (это не масштабирование относительно указателя мыши). Также событие прокрутки не генерируется, если указатель мыши находится за пределами самого внешнего круга. Это мой код:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import javafx.stage.Stage;


public class MainApp extends Application {
    Pane pane;
    Pane centerPane;
    Pane topPane;
    Pane bottomPane;
    Pane leftPane;
    Pane rightPane;

    Label topLabel;
    Label bottomLabel;

    Button leftButton;
    Button rightButton;

    Circle face;

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

    @Override
    public void start(Stage primaryStage) {
        pane = new Pane();
        pane.setPrefWidth(Screen.getPrimary().getVisualBounds().getWidth());
        pane.setPrefHeight(Screen.getPrimary().getVisualBounds().getHeight() - 25.0);

        topLabel = new Label("Top");
        bottomLabel = new Label("Bottom");

        leftButton = new Button("Left");
        rightButton = new Button("Right");

        bottomPane = new Pane();
        bottomPane.setStyle("-fx-border-color: black; -fx-background-color: #fff");
        bottomPane.prefWidthProperty().bind(pane.prefWidthProperty());
        bottomPane.prefHeightProperty().bind(bottomLabel.prefHeightProperty());
        bottomPane.layoutYProperty().bind(pane.prefHeightProperty().subtract(bottomLabel.heightProperty()));
        bottomPane.getChildren().addAll(bottomLabel);

        topPane = new Pane();
        topPane.setStyle("-fx-border-color: black; -fx-background-color: #fff");
        topPane.prefWidthProperty().bind(pane.prefWidthProperty());
        topPane.prefHeightProperty().bind(topLabel.prefHeightProperty());
        topPane.getChildren().addAll(topLabel);

        leftPane = new Pane();
        leftPane.setStyle("-fx-border-color: black; -fx-background-color: #fff");
        leftPane.prefWidthProperty().bind(leftButton.widthProperty());
        leftPane.prefHeightProperty().bind(pane.prefHeightProperty().subtract(topPane.prefHeightProperty()).subtract(bottomPane.prefHeightProperty()));
        leftPane.layoutYProperty().bind(topPane.layoutYProperty().add(topLabel.heightProperty()));
        leftPane.getChildren().addAll(leftButton);

        rightPane = new Pane();
        rightPane.setStyle("-fx-border-color: black; -fx-background-color: #fff");
        rightPane.prefWidthProperty().bind(rightButton.widthProperty());
        rightPane.prefHeightProperty().bind(pane.prefHeightProperty().subtract(topPane.prefHeightProperty()).subtract(bottomPane.prefHeightProperty()));
        rightPane.layoutXProperty().bind(pane.prefWidthProperty().subtract(leftPane.prefWidthProperty()));
        rightPane.layoutYProperty().bind(topPane.layoutYProperty().add(topLabel.heightProperty()));
        rightPane.getChildren().addAll(rightButton);

        centerPane = new Pane();
        centerPane.prefWidthProperty().bind(pane.prefWidthProperty().subtract(leftPane.prefWidthProperty().subtract(rightPane.prefWidthProperty())));
        centerPane.prefHeightProperty().bind(pane.prefHeightProperty().subtract(topPane.prefHeightProperty().subtract(bottomPane.prefHeightProperty())));

        for(int i = 5; i > 0; --i) {
            Circle circle = new Circle(i * 60);
            circle.setFill(Color.GREEN);
            circle.setStroke(Color.RED);
            centerPane.getChildren().addAll(circle);

            if(i == 5)
                face = circle;
        }
        centerPane.widthProperty().addListener((observable, oldValue, newValue) -> {
            restore();
        });

        centerPane.heightProperty().addListener((observable, oldValue, newValue) -> {
            restore();
        });

        pane.getChildren().addAll(centerPane, rightPane, leftPane, bottomPane, topPane);

        centerPane.setOnScroll(new EventHandler<ScrollEvent>() {
            @Override
            public void handle(ScrollEvent scrollEvent) {
                if(Math.abs(scrollEvent.getDeltaY()) <= 1E-6)
                    return;

                double delta = 1.2;
                double scale = (scrollEvent.getDeltaY() < 0.0) ? (1 / delta) : delta;

                zoom(scale, scrollEvent.getScreenX(), scrollEvent.getScreenY());
            }
        });

        primaryStage.setTitle("ARCHERY");
        primaryStage.setMaximized(true);
        primaryStage.setScene(new Scene(pane, Screen.getPrimary().getVisualBounds().getWidth(), Screen.getPrimary().getVisualBounds().getHeight()));
        primaryStage.show();
    }


    void restore() {
        centerPane.setTranslateX((centerPane.getWidth() + rightPane.getWidth()) / 2.0 - face.getCenterX());
        centerPane.setTranslateY((bottomPane.getLayoutY() - topPane.getHeight()) / 2.0 - face.getCenterY());

        centerPane.setScaleX(1.0);
        centerPane.setScaleY(1.0);
    }


    void zoom(double scale, double eventX, double eventY) {
        double oldScale = centerPane.getScaleX();
        double nextScale = scale * centerPane.getScaleX();

        double MIN_SCALE = 0.01;
        double MAX_SCALE = 50000.0 * 2 / 0.01; //Upto 10m resolution

        if (nextScale > MAX_SCALE)
            nextScale = MAX_SCALE; //Restricts max scale to 10m resolution
        else if (nextScale < MIN_SCALE)
            nextScale = MIN_SCALE; //Restricts min scale to 1

        centerPane.setScaleX(nextScale);
        centerPane.setScaleY(nextScale);

        Bounds boundsInScene = centerPane.localToScene(centerPane.getBoundsInLocal());
        double dx = (eventX - (boundsInScene.getWidth() / 2 + boundsInScene.getMinX()));
        double dy = (eventY - (boundsInScene.getHeight() / 2 + boundsInScene.getMinY()));

        double f = (nextScale / oldScale) - 1;
        centerPane.setTranslateX(centerPane.getTranslateX() - f * dx);
        centerPane.setTranslateY(centerPane.getTranslateY() - f * dy);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...