【问题标题】:Move a child stage when moving parent stage on Windows在 Windows 上移动父级时移动子级
【发布时间】:2020-07-22 22:52:39
【问题描述】:

我想知道当我们在 Windows 上移动父级时,是否有办法将 JavaFX 子级与其父级一起移动。事实上,在 MacOS 上,这似乎是默认行为。正如您在此视频中看到的:https://imgur.com/a/r3qIklu,我可以独立移动缩略图场景,当我移动主窗口时,缩略图(顺便说一句,这是主窗口的子场景)仍然“附加”到父窗口,并且跟着它。

但是,在 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();
}

【问题讨论】:

  • (第一个视频链接坏了。)缩略图必须是舞台吗?您能否将它的根和主 Stage 的根放在 AnchorPane 中,并让该 AnchorPane 成为主 Stage 的新根?
  • 顺便说一句:您的资源参数错误 - 请阅读 java 文档并遵守它指定的内容
  • @VGR 感谢您的回答,我更新了第一个视频链接 (imgur.com/a/r3qIklu)。要回答您的问题,缩略图不一定必须是场景。您能否详细说明您提出的解决方案?它会帮助我理解它(事实上,我是 JavaFx 的新手)提前谢谢!

标签: java windows user-interface javafx


【解决方案1】:

将您的根目录和缩略图根放在一个常规的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 文件中完成相同的功能:只需将背景和缩略图放在窗格中。如果您愿意,您也可以在那里添加鼠标事件处理程序。

这是我用作 parent-stage-background.png 的图像:

这是我用作 thumbnail-background.png 的图片:

【讨论】:

  • 谢谢,我试试看!
猜你喜欢
  • 2019-12-15
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 2017-01-24
相关资源
最近更新 更多