JavaFX - Перекрывающиеся панели - PullRequest
1 голос
/ 02 февраля 2020

Я пытаюсь найти решение, где слой может перекрывать другой слой, не подталкивая его в каком-либо направлении. Примерно так: https://docs.oracle.com/javase/7/docs/api/javax/swing/JLayeredPane.html, но в JavaFX.

Кажется, что это очень базовая c функция, но я не могу найти решение.

Я хотел бы добиться чего-то вроде следующего:

Я хотел бы root 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


Любая помощь приветствуется.

Обновление: Пример изображения

Example image

Ответы [ 2 ]

2 голосов
/ 03 февраля 2020

То же, что и предложение @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);
    }
}
1 голос
/ 03 февраля 2020

Вы можете использовать простое 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()) );
...