Автоматическое изменение размера окна на основе динамического содержимого - PullRequest
0 голосов
/ 28 ноября 2018

Я проверяю возможность автоматического изменения размера окна в зависимости от содержимого.Я уже осведомлен о методе Window.sizeToScene().Но это так обременительно, что мне нужно позаботиться о каждом месте, чтобы вызвать sizeToScene ().Например, когда я добавляю / удаляю узлы, когда я раскрываю titlePanes и т. Д. *

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

Любые советы / предложения очень ценятся.

Ниже приведена краткая демонстрация того, что я ищу.Все работает, как и ожидалось, если я рассмотрю вызов sizeToScene ().Я нацеливаюсь на способ получить такое же поведение без вызова sizeToScene для каждого сценария.

enter image description here

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class TransparentWindowResizeDemo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        VBox root = new VBox();
        root.setSpacing(15);
        root.setAlignment(Pos.CENTER);

        Scene sc = new Scene(root, 300, 300);
        stage.setScene(sc);
        stage.show();

        Button showNormal = new Button("Show Normal Window");
        showNormal.setOnAction(e -> showWindow(false));

        Button showTransparent = new Button("Show Transparent Window");
        showTransparent.setOnAction(e -> showWindow(true));

        root.getChildren().addAll(showNormal, showTransparent);
    }

    private void showWindow(boolean isTransparent) {
        Stage window = new Stage();
        VBox root = new VBox();
        root.setStyle("-fx-background-color: grey; -fx-border-width:2px;-fx-border-color:black;");
        Scene scene = new Scene(root, Color.TRANSPARENT);
        window.setScene(scene);

        VBox layout = new VBox();
        layout.setSpacing(5);
        layout.setPadding(new Insets(5));

        CheckBox sizeToScene = new CheckBox("sizeToScene");
        sizeToScene.setSelected(true);

        StackPane box = new StackPane();
        box.setStyle("-fx-background-color:yellow; -fx-border-width:1px;-fx-border-color:black;");
        box.setMinSize(200, 100);
        box.setMaxSize(200, 100);

        Button add = new Button("Add Pane");
        Button remove = new Button("Remove Pane");
        remove.setDisable(true);
        add.setOnAction(e -> {
            layout.getChildren().add(box);
            add.setDisable(true);
            remove.setDisable(false);
            if (sizeToScene.isSelected()) {
                window.sizeToScene();
            }
        });
        remove.setOnAction(e -> {
            layout.getChildren().remove(box);
            add.setDisable(false);
            remove.setDisable(true);
            if (sizeToScene.isSelected()) {
                window.sizeToScene();
            }
        });
        HBox btnLayout = new HBox();
        btnLayout.setSpacing(5);
        btnLayout.getChildren().addAll(add, remove);

        StackPane tpContent = new StackPane();
        tpContent.setStyle("-fx-background-color:pink; -fx-border-width:1px;-fx-border-color:black;");
        tpContent.setMinSize(200, 100);
        tpContent.setMaxSize(200, 100);

        TitledPane tp = new TitledPane("Titled Pane", tpContent);
        tp.setAnimated(false);
        tp.expandedProperty().addListener((obs, oldVal, newVal) -> {
            if (sizeToScene.isSelected()) {
                window.sizeToScene();
            }
        });

        if (isTransparent) {
            window.initStyle(StageStyle.TRANSPARENT);

            StackPane close = new StackPane();
            close.setMaxWidth(30);
            close.setStyle("-fx-background-color:red;");
            close.getChildren().add(new Label("X"));
            close.setOnMouseClicked(e -> window.hide());

            DoubleProperty x = new SimpleDoubleProperty();
            DoubleProperty y = new SimpleDoubleProperty();
            StackPane header = new StackPane();
            header.setOnMousePressed(e -> {
                x.set(e.getSceneX());
                y.set(e.getSceneY());
            });
            header.setOnMouseDragged(e -> {
                window.setX(e.getScreenX() - x.get());
                window.setY(e.getScreenY() - y.get());
            });
            header.setStyle("-fx-border-width:0px 0px 2px 0px;-fx-border-color:black;");
            header.setMinHeight(30);
            header.setAlignment(Pos.CENTER_RIGHT);
            Label lbl = new Label("I am draggable !!");
            lbl.setStyle("-fx-text-fill:white;-fx-font-weight:bold;");
            StackPane.setAlignment(lbl,Pos.CENTER_LEFT);
            header.getChildren().addAll(lbl,close);
            root.getChildren().add(header);
        }

        layout.getChildren().addAll(sizeToScene, btnLayout, tp);
        root.getChildren().add(layout);
        window.show();

    }

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

Редактировать :: Это отличается от того, что я уже нашел в других вопросах или со ссылкой в ​​комментарии.Указанное решение - это то, что я знаю, и я уже упоминал об этом в этом вопросе.У меня тяжелый экран, где он содержит много разных узлов.Я проверяю любое общее решение для включения в одном месте, а не в сценарии добавления / удаления каждого узла.

1 Ответ

0 голосов
/ 28 ноября 2018

Я бы сказал, что это не изящное решение (это больше похоже на взлом), но, по крайней мере, оно сработало на вашем примере:

VBox root = new VBox() {
    private boolean needsResize = false;

    @Override
    protected void layoutChildren()
    {
        super.layoutChildren();

        if (!needsResize) {
            needsResize = true;

            Platform.runLater(() -> {
                if (needsResize) {
                    window.sizeToScene();
                    needsResize = false;
                }
            });
        }
    }
};

Конечно, вы должны добавить в sizeToScene.isSelected()часть, и вы также можете сделать это фактическим подклассом.

...