根据动态内容自动调整 window 的大小
Automatically resizing the window based on dynamic content
我正在检查一项功能,可以根据内容自动调整 window 的大小。我已经知道 Window.sizeToScene()
方法。但这太麻烦了,我需要在每个地方都小心地调用 sizeToScene()。例如,当我 add/remove 个节点时,当我展开 titlePanes 等时...
谁能告诉我是否可以根据内容自动调整 window。我正在寻找正常和透明的此功能 windows。
非常感谢hints/suggestion。
请在下面找到我正在寻找的快速演示。如果我考虑调用 sizeToScene(),一切都会按预期工作。我的目标是寻找一种无需为每个场景都调用 sizeToScene 即可获得相同行为的方法。
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);
}
}
Edit :: 这与我在其他问题或评论中的 link 中已经发现的不同。指定的解决方案是我所知道的,我已经在问题中提到过。我有一个沉重的屏幕,其中包含许多不同层次的节点。我正在检查要包含在一个地方的任何通用解决方案,而不是从每个节点调用 add/remove 场景。
我会说这不是一个优雅的解决方案(它更像是一个 hack),但至少它在使用您的示例时有效:
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()
部分加上,你也可以把它做成一个实际的子类。
我正在检查一项功能,可以根据内容自动调整 window 的大小。我已经知道 Window.sizeToScene()
方法。但这太麻烦了,我需要在每个地方都小心地调用 sizeToScene()。例如,当我 add/remove 个节点时,当我展开 titlePanes 等时...
谁能告诉我是否可以根据内容自动调整 window。我正在寻找正常和透明的此功能 windows。
非常感谢hints/suggestion。
请在下面找到我正在寻找的快速演示。如果我考虑调用 sizeToScene(),一切都会按预期工作。我的目标是寻找一种无需为每个场景都调用 sizeToScene 即可获得相同行为的方法。
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);
}
}
Edit :: 这与我在其他问题或评论中的 link 中已经发现的不同。指定的解决方案是我所知道的,我已经在问题中提到过。我有一个沉重的屏幕,其中包含许多不同层次的节点。我正在检查要包含在一个地方的任何通用解决方案,而不是从每个节点调用 add/remove 场景。
我会说这不是一个优雅的解决方案(它更像是一个 hack),但至少它在使用您的示例时有效:
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()
部分加上,你也可以把它做成一个实际的子类。