JavaFX - 重叠窗格
JavaFX - Overlapping panes
我正在尝试找到一种解决方案,其中一层可以与另一层重叠而不会将其推向任何方向。类似这样:https://docs.oracle.com/javase/7/docs/api/javax/swing/JLayeredPane.html 但在 JavaFX 中。
这似乎是一个非常基本的功能,但我真的找不到解决方案。
我想达到的效果如下:
我想要一个根 Node
,比方说 BorderPane
,在它的 left
中有一个(设置)pane
在它的 center
主要内容。当用户单击 center
中的按钮时,会显示 left
窗格,而不会将 center
窗格推到右侧。这就是问题所在,因为所需的行为是覆盖居中的内容而不是旁边的内容。
toFront
和 toBack
函数乍一看似乎是一个可能的解决方案,但它只会改变渲染顺序。
不幸的是,我不认为这个问题可以用 BorderPane
来解决,因为它无法管理重叠。但愿我在这里错了。使用 BorderPane
并不是强制性的。如果它的工作方式与我在上一节中提到的类似就足够了。
也许可以用 SubScene
来实现,但我真的不知道怎么做。
SubScene
文档: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/SubScene.html
非常感谢任何帮助。
更新:示例图片
您可以使用一个简单的 Pane
来处理主要内容和配置重叠窗格,然后在主要内容中添加一个侦听器来更改配置窗格的可见性。
Pane container = new Pane();
Pane mainContent = ... ;
// you main content pane stuff
Pane config = ... ;
// your config pane stuff
container.getChildren().addAll(mainContent, config); // in this order
mainContent.setOnMouseClicked(e -> config.setVisible( ! config.isVisible()) );
与@Nand 和@LBald 的建议相同,我也认为 StackPane 在这种情况下可能是一个不错的选择。下面是一个快速演示,显示带有淡入淡出效果的叠加节点。
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.stream.Stream;
public class OverlayLayout_Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("Node Overlay Demo");
primaryStage.show();
HBox hBox = new HBox(new Button("One"), new Button("Two"));
hBox.setPadding(new Insets(10));
hBox.setSpacing(10);
StackPane hPane = new StackPane(hBox);
hPane.setMaxHeight(100);
hPane.setVisible(false);
hPane.setStyle("-fx-background-color:#55555550");
VBox vBox = new VBox(new Button("One"), new Button("Two"));
vBox.setPadding(new Insets(10));
vBox.setSpacing(10);
StackPane vPane = new StackPane(vBox);
vPane.setMaxWidth(100);
vPane.setVisible(false);
vPane.setStyle("-fx-background-color:#55555550");
Button left = new Button("Left");
Button top = new Button("Top");
Button right = new Button("Right");
Button bottom = new Button("Bottom");
VBox buttons = new VBox(left, top, right, bottom);
buttons.setStyle("-fx-border-width:2px;-fx-border-color:black;");
buttons.setSpacing(10);
buttons.setAlignment(Pos.CENTER);
StackPane.setMargin(buttons, new Insets(15));
StackPane content = new StackPane(buttons);
content.setOnMouseClicked(e -> {
Node node = vPane.isVisible() ? vPane : hPane;
FadeTransition ft = new FadeTransition(Duration.millis(300), node);
ft.setOnFinished(e1 -> node.setVisible(false));
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.play();
});
root.getChildren().addAll(content, hPane, vPane);
Stream.of(left, top, right, bottom).forEach(button -> {
button.setOnAction(e -> {
vPane.setVisible(false);
hPane.setVisible(false);
Node node;
switch (button.getText()) {
case "Left":
case "Right":
node = vPane;
StackPane.setAlignment(vPane, button.getText().equals("Left") ? Pos.CENTER_LEFT : Pos.CENTER_RIGHT);
break;
default:
node = hPane;
StackPane.setAlignment(hPane, button.getText().equals("Top") ? Pos.TOP_CENTER : Pos.BOTTOM_CENTER);
}
node.setVisible(true);
FadeTransition ft = new FadeTransition(Duration.millis(300), node);
ft.setFromValue(0.0);
ft.setToValue(1.0);
ft.play();
});
});
}
public static void main(String... args) {
Application.launch(args);
}
}
我正在尝试找到一种解决方案,其中一层可以与另一层重叠而不会将其推向任何方向。类似这样:https://docs.oracle.com/javase/7/docs/api/javax/swing/JLayeredPane.html 但在 JavaFX 中。
这似乎是一个非常基本的功能,但我真的找不到解决方案。
我想达到的效果如下:
我想要一个根 Node
,比方说 BorderPane
,在它的 left
中有一个(设置)pane
在它的 center
主要内容。当用户单击 center
中的按钮时,会显示 left
窗格,而不会将 center
窗格推到右侧。这就是问题所在,因为所需的行为是覆盖居中的内容而不是旁边的内容。
toFront
和 toBack
函数乍一看似乎是一个可能的解决方案,但它只会改变渲染顺序。
不幸的是,我不认为这个问题可以用 BorderPane
来解决,因为它无法管理重叠。但愿我在这里错了。使用 BorderPane
并不是强制性的。如果它的工作方式与我在上一节中提到的类似就足够了。
也许可以用 SubScene
来实现,但我真的不知道怎么做。
SubScene
文档: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/SubScene.html
非常感谢任何帮助。
更新:示例图片
您可以使用一个简单的 Pane
来处理主要内容和配置重叠窗格,然后在主要内容中添加一个侦听器来更改配置窗格的可见性。
Pane container = new Pane();
Pane mainContent = ... ;
// you main content pane stuff
Pane config = ... ;
// your config pane stuff
container.getChildren().addAll(mainContent, config); // in this order
mainContent.setOnMouseClicked(e -> config.setVisible( ! config.isVisible()) );
与@Nand 和@LBald 的建议相同,我也认为 StackPane 在这种情况下可能是一个不错的选择。下面是一个快速演示,显示带有淡入淡出效果的叠加节点。
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.stream.Stream;
public class OverlayLayout_Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
Scene scene = new Scene(root, 500, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("Node Overlay Demo");
primaryStage.show();
HBox hBox = new HBox(new Button("One"), new Button("Two"));
hBox.setPadding(new Insets(10));
hBox.setSpacing(10);
StackPane hPane = new StackPane(hBox);
hPane.setMaxHeight(100);
hPane.setVisible(false);
hPane.setStyle("-fx-background-color:#55555550");
VBox vBox = new VBox(new Button("One"), new Button("Two"));
vBox.setPadding(new Insets(10));
vBox.setSpacing(10);
StackPane vPane = new StackPane(vBox);
vPane.setMaxWidth(100);
vPane.setVisible(false);
vPane.setStyle("-fx-background-color:#55555550");
Button left = new Button("Left");
Button top = new Button("Top");
Button right = new Button("Right");
Button bottom = new Button("Bottom");
VBox buttons = new VBox(left, top, right, bottom);
buttons.setStyle("-fx-border-width:2px;-fx-border-color:black;");
buttons.setSpacing(10);
buttons.setAlignment(Pos.CENTER);
StackPane.setMargin(buttons, new Insets(15));
StackPane content = new StackPane(buttons);
content.setOnMouseClicked(e -> {
Node node = vPane.isVisible() ? vPane : hPane;
FadeTransition ft = new FadeTransition(Duration.millis(300), node);
ft.setOnFinished(e1 -> node.setVisible(false));
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.play();
});
root.getChildren().addAll(content, hPane, vPane);
Stream.of(left, top, right, bottom).forEach(button -> {
button.setOnAction(e -> {
vPane.setVisible(false);
hPane.setVisible(false);
Node node;
switch (button.getText()) {
case "Left":
case "Right":
node = vPane;
StackPane.setAlignment(vPane, button.getText().equals("Left") ? Pos.CENTER_LEFT : Pos.CENTER_RIGHT);
break;
default:
node = hPane;
StackPane.setAlignment(hPane, button.getText().equals("Top") ? Pos.TOP_CENTER : Pos.BOTTOM_CENTER);
}
node.setVisible(true);
FadeTransition ft = new FadeTransition(Duration.millis(300), node);
ft.setFromValue(0.0);
ft.setToValue(1.0);
ft.play();
});
});
}
public static void main(String... args) {
Application.launch(args);
}
}