Я работаю над проектом 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);
}
}