在 Windows 上移动父阶段时移动子阶段
Move a child stage when moving parent stage on Windows
我想知道当我们在 Windows 上移动父阶段时,是否有办法将 JavaFX 子阶段与其父阶段一起移动。实际上,在 MacOS 上这似乎是默认行为。正如您在此视频中看到的:https://imgur.com/a/r3qIklu,我可以独立移动缩略图场景,当我移动主要 window 时,缩略图(这是主要 window 顺便说一句的子场景), 仍然“附加”到父级并跟随它。
但是,在 Windows 上,正如您在此处看到的:https://imgur.com/a/SPEkYJ2,结果不一样。当父级移动时,缩略图会保持在当前位置。如何在 Windows 上重现 MacOS 行为?
作为参考,我的阶段是这样初始化的:
public void start(Stage primaryStage) {
//App's main stage
Parent root = FXMLLoader.load(getClass().getResource("../spaception.fxml"));
Scene scene = new Scene(root, 1400, 700);
primaryStage.setScene(scene);
primaryStage.show();
//...
//Child stage (Thumbnail)
Parent thumbnailRoot = FXMLLoader.load(getClass().getResource("../thumbnail.fxml"));
Stage thumbnailStage = new Stage();
thumbnailStage.initOwner(primaryStage);
thumbnailStage.initStyle(StageStyle.UNDECORATED);
thumbnailStage.setX(primaryStage.getX()+1100);
thumbnailStage.setY(primaryStage.getY()+540);
Scene scene = new Scene(thumbnailRoot, 250, 145);
thumbnailStage.setScene(scene);
thumbnailStage.show();
}
将 root 和 thumbnailRoot 一起放在一个常规 Pane 中(相当于 Swing 中的空布局)。
为了允许用户移动 thumbnailRoot,向其添加鼠标事件处理程序以进行按下和拖动,并保留跟踪 thumbnailRoot 位置和跟踪鼠标拖动的私有字段。
简单示例实现:
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.Pane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
public class ParentAndThumbnail
extends Application {
private Bounds thumbnailBoundsOnPress;
private double pressedX;
private double pressedY;
@Override
public void start(Stage stage) {
Label positionLabel = new Label("Current position: x y");
VBox left =
new VBox(6, new Button("+"), new Button("-"), new Button("C"));
left.setFillWidth(true);
left.setPadding(new Insets(6));
left.getChildren().forEach(
c -> ((Button) c).setMaxWidth(Double.MAX_VALUE));
VBox right =
new VBox(6, new Button("+"), new Button("-"), new Button("C"));
right.setFillWidth(true);
right.setPadding(new Insets(6));
right.getChildren().forEach(
c -> ((Button) c).setMaxWidth(Double.MAX_VALUE));
MenuBar menuBar = new MenuBar(
new Menu("File", null,
new MenuItem("New"),
new MenuItem("Open"),
new MenuItem("Save"),
new MenuItem("Exit")),
new Menu("Edit", null,
new MenuItem("Cut"),
new MenuItem("Copy"),
new MenuItem("Paste")));
ImageView imagePane =
new ImageView(new Image("parent-stage-background.png"));
BorderPane root = new BorderPane(
imagePane, menuBar, left, positionLabel, right);
BorderPane thumbnailRoot = new BorderPane(
new ImageView(new Image("thumbnail-background.png")));
thumbnailRoot.setStyle(
"-fx-border-width: 4px 30px 4px 30px; " +
"-fx-border-color: black");
thumbnailRoot.setOnMousePressed(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
thumbnailBoundsOnPress = thumbnailRoot.getBoundsInParent();
pressedX = e.getScreenX();
pressedY = e.getScreenY();
}
});
thumbnailRoot.setOnMouseDragged(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
thumbnailRoot.setLayoutX(
thumbnailBoundsOnPress.getMinX()
+ e.getScreenX() - pressedX);
thumbnailRoot.setLayoutY(
thumbnailBoundsOnPress.getMinY()
+ e.getScreenY() - pressedY);
}
});
Pane overlay = new Pane();
overlay.getChildren().addAll(root, thumbnailRoot);
stage.setOnShown(e -> {
thumbnailRoot.setLayoutX(root.getWidth() - 400);
thumbnailRoot.setLayoutY(root.getHeight() - 200);
});
stage.setScene(new Scene(overlay));
stage.setTitle("Spaception");
stage.show();
}
public static class Main {
public static void main(String[] args) {
Application.launch(ParentAndThumbnail.class, args);
}
}
}
您可以在 .fxml 文件中完成相同的功能:只需将背景和缩略图放在窗格中。如果您愿意,您也可以在那里添加鼠标事件处理程序。
这是我用作父阶段的图像-background.png:
这是我用作缩略图的图像-background.png:
我想知道当我们在 Windows 上移动父阶段时,是否有办法将 JavaFX 子阶段与其父阶段一起移动。实际上,在 MacOS 上这似乎是默认行为。正如您在此视频中看到的:https://imgur.com/a/r3qIklu,我可以独立移动缩略图场景,当我移动主要 window 时,缩略图(这是主要 window 顺便说一句的子场景), 仍然“附加”到父级并跟随它。
但是,在 Windows 上,正如您在此处看到的:https://imgur.com/a/SPEkYJ2,结果不一样。当父级移动时,缩略图会保持在当前位置。如何在 Windows 上重现 MacOS 行为?
作为参考,我的阶段是这样初始化的:
public void start(Stage primaryStage) {
//App's main stage
Parent root = FXMLLoader.load(getClass().getResource("../spaception.fxml"));
Scene scene = new Scene(root, 1400, 700);
primaryStage.setScene(scene);
primaryStage.show();
//...
//Child stage (Thumbnail)
Parent thumbnailRoot = FXMLLoader.load(getClass().getResource("../thumbnail.fxml"));
Stage thumbnailStage = new Stage();
thumbnailStage.initOwner(primaryStage);
thumbnailStage.initStyle(StageStyle.UNDECORATED);
thumbnailStage.setX(primaryStage.getX()+1100);
thumbnailStage.setY(primaryStage.getY()+540);
Scene scene = new Scene(thumbnailRoot, 250, 145);
thumbnailStage.setScene(scene);
thumbnailStage.show();
}
将 root 和 thumbnailRoot 一起放在一个常规 Pane 中(相当于 Swing 中的空布局)。
为了允许用户移动 thumbnailRoot,向其添加鼠标事件处理程序以进行按下和拖动,并保留跟踪 thumbnailRoot 位置和跟踪鼠标拖动的私有字段。
简单示例实现:
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.Pane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
public class ParentAndThumbnail
extends Application {
private Bounds thumbnailBoundsOnPress;
private double pressedX;
private double pressedY;
@Override
public void start(Stage stage) {
Label positionLabel = new Label("Current position: x y");
VBox left =
new VBox(6, new Button("+"), new Button("-"), new Button("C"));
left.setFillWidth(true);
left.setPadding(new Insets(6));
left.getChildren().forEach(
c -> ((Button) c).setMaxWidth(Double.MAX_VALUE));
VBox right =
new VBox(6, new Button("+"), new Button("-"), new Button("C"));
right.setFillWidth(true);
right.setPadding(new Insets(6));
right.getChildren().forEach(
c -> ((Button) c).setMaxWidth(Double.MAX_VALUE));
MenuBar menuBar = new MenuBar(
new Menu("File", null,
new MenuItem("New"),
new MenuItem("Open"),
new MenuItem("Save"),
new MenuItem("Exit")),
new Menu("Edit", null,
new MenuItem("Cut"),
new MenuItem("Copy"),
new MenuItem("Paste")));
ImageView imagePane =
new ImageView(new Image("parent-stage-background.png"));
BorderPane root = new BorderPane(
imagePane, menuBar, left, positionLabel, right);
BorderPane thumbnailRoot = new BorderPane(
new ImageView(new Image("thumbnail-background.png")));
thumbnailRoot.setStyle(
"-fx-border-width: 4px 30px 4px 30px; " +
"-fx-border-color: black");
thumbnailRoot.setOnMousePressed(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
thumbnailBoundsOnPress = thumbnailRoot.getBoundsInParent();
pressedX = e.getScreenX();
pressedY = e.getScreenY();
}
});
thumbnailRoot.setOnMouseDragged(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
thumbnailRoot.setLayoutX(
thumbnailBoundsOnPress.getMinX()
+ e.getScreenX() - pressedX);
thumbnailRoot.setLayoutY(
thumbnailBoundsOnPress.getMinY()
+ e.getScreenY() - pressedY);
}
});
Pane overlay = new Pane();
overlay.getChildren().addAll(root, thumbnailRoot);
stage.setOnShown(e -> {
thumbnailRoot.setLayoutX(root.getWidth() - 400);
thumbnailRoot.setLayoutY(root.getHeight() - 200);
});
stage.setScene(new Scene(overlay));
stage.setTitle("Spaception");
stage.show();
}
public static class Main {
public static void main(String[] args) {
Application.launch(ParentAndThumbnail.class, args);
}
}
}
您可以在 .fxml 文件中完成相同的功能:只需将背景和缩略图放在窗格中。如果您愿意,您也可以在那里添加鼠标事件处理程序。
这是我用作父阶段的图像-background.png:
这是我用作缩略图的图像-background.png: