JavaFX:多个“视图”、“页面”或场景-如何实现?

vbopmzt1  于 2022-12-28  发布在  Java
关注(0)|答案(1)|浏览(192)

我正在尝试用JavaFX建立一个虚拟的网店。我故意不使用fxml,scenebuilder,maven或任何其他构建工具。只是普通的JavaFX,为了真正了解基础知识。然而,我遇到了一个问题,创建和导航不同的'页面'。
我尝试过各种创造性的解决方案,比如this one(允许发布链接吗?),但没有一个完全适合我,因为我希望每个“页面”、“视图”或场景都在一个单独的java类文件中,以保持一切结构化和有序。
我想我应该做一个边界窗格作为每个页面的父布局

abstract class WindowBase extends BorderPane {

    public abstract BorderPane render(App app);

    public WindowBase() {
    
        Label labelTop = new Label("Top box");

        HBox topBox = new HBox();
        topBox.setStyle("-fx-background-color: red;");
        topBox.getChildren().addAll(labelTop);

        Label labelLeft = new Label("Left box");

        VBox leftBox = new VBox();
        leftBox.setStyle("-fx-background-color: green;");
        leftBox.getChildren().addAll(labelLeft);

        Label labelRight = new Label("Right box");

        VBox rightBox = new VBox();
        rightBox.setStyle("-fx-background-color: blue;");
        rightBox.getChildren().addAll(labelRight);

        Label labelBottom = new Label("Bottom box");

        HBox bottomBox = new HBox();
        bottomBox.setStyle("-fx-background-color: yellow;");
        bottomBox.getChildren().addAll(labelBottom);

        this.setTop(topBox);
        this.setLeft(leftBox);
        this.setRight(rightBox);
        this.setBottom(bottomBox);
    }
}

孩子,主页

public class Homepage extends WindowBase {

    public BorderPane render(App app) {

        Button button = new Button("Go to shopping cart");
        button.setOnAction((event) -> app.toShoppingCart());

        StackPane centerPane = new StackPane();
        centerPane.getChildren().add(button);
        this.setCenter(centerPane);

        return this;
    }
}

最后是我的App.java,它运行所有的东西

public class App extends Application{

    private WindowBase view;

    public void start(Stage stage) throws Exception {

        view = new Homepage();

        stage.setScene(new Scene(view.render(this)));
        stage.setFullScreen(true);
        stage.show();

    }

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    public void toHomepage() {
        this.view = new Homepage();
    }

    public void toShoppingCart() {
        this.view = new ShoppingCart();
    }
}

我知道我不能将这个(App)作为参数传递给view.render(),在方法render中使用这个参数并期望能够操纵它,因为它只会在到达那里时创建一个新的App示例。
我试着将导航按钮放在App类中,以便能够操纵视图,但是我无法从后续视图中调用这些按钮。
一定有一种方法不用在一个文件中编写完整的GUI就可以实现我想要的东西,对吗?我应该让我的视图保持静态,对吗?
除了BorderPanes,我当然也可以使用场景,无论什么工作。

3zwjbxry

3zwjbxry1#

我已经想出了我想要的解决方案。把它贴在这里给任何遇到同样情况的人。
类窗口库

public class WindowBase {

    public BorderPane getMainPane() {
    
        Label labelTop = new Label("Top box");
    
        HBox topBox = new HBox();
        topBox.setStyle("-fx-background-color: red;");
        topBox.getChildren().addAll(labelTop);

        Label labelLeft = new Label("Left box");

        VBox leftBox = new VBox();
        leftBox.setStyle("-fx-background-color: green;");
        leftBox.getChildren().addAll(labelLeft);

        Label labelRight = new Label("Right box");

        VBox rightBox = new VBox();
        rightBox.setStyle("-fx-background-color: blue;");
        rightBox.getChildren().addAll(labelRight);

        Label labelBottom = new Label("Bottom box");

        HBox bottomBox = new HBox();
        bottomBox.setStyle("-fx-background-color: yellow;");
        bottomBox.getChildren().addAll(labelBottom);

        BorderPane borderPane = new BorderPane();

        borderPane.setTop(topBox);
        borderPane.setLeft(leftBox);
        borderPane.setRight(rightBox);
        borderPane.setBottom(bottomBox);

        return borderPane;
    }
}

班级主页

public class Homepage extends WindowBase {

    public BorderPane render(Button toShoppingCart) {

        Label label = new Label("This is the homepage.");
        label.setStyle(
                "-fx-font: normal bold 30px 'elephant'; -fx-text-fill: black; -fx-background-color: red;");

        StackPane stackPane = new StackPane();
        stackPane.getChildren().addAll(label);

        BorderPane mainPane = getMainPane();
        VBox leftBox = (VBox) mainPane.getLeft();
        leftBox.getChildren().add(toShoppingCart);

        //I do not understand why this works. I abstracted leftBox from mainPane, then added shoppingCart, but never added the abstracted
        //  leftBox back to the mainPane before returning it. This should not work, but it does. leftBox.getChildren().add(toShoppingCart)
        //  should have no effect.
        //However, mainPane.getChildren().add(leftBox) throws an IllegalArgumentException about duplicate components, which is to be
        //  expected if the leftBox is already automatically added back to the mainPane.

        mainPane.setCenter(stackPane);

        return mainPane;
    }
}

类购物车

public class ShoppingCart extends WindowBase {

    public ShoppingCart() {
        super();
    }

    public BorderPane render(Button toHomepage) {
        
        Label label = new Label("This is the shopping cart.");
        label.setStyle(
            "-fx-font: normal bold 30px 'elephant'; -fx-text-fill: black; -fx-background-color: red;");
        
        StackPane centerPane = new StackPane();
        centerPane.getChildren().add(label);
    
        BorderPane mainPane = getMainPane();
        VBox leftBox = (VBox) mainPane.getLeft();
        leftBox.getChildren().add(toHomepage);

        mainPane.setCenter(centerPane);

        return mainPane;
    }
}

类应用程序

public class App extends Application{

    Scene scene;

    @Override
    public void start(Stage stage) throws Exception {

        Homepage homePane = new Homepage();
        Button toHomepage = new Button("Back to home page");

        ShoppingCart shoppingPane = new ShoppingCart();
        Button toShoppingCart = new Button("To shopping cart");

        toHomepage.setOnAction(e -> scene.setRoot(homePane.render(toShoppingCart)));
        toShoppingCart.setOnAction(e -> scene.setRoot(shoppingPane.render(toHomepage)));

        scene = new Scene(homePane.render(toShoppingCart), 600, 400);

        stage.setScene(scene);
        stage.setFullScreen(true);
        stage.show();

    }

    public static void main(String[] args) throws Exception {
        
        launch(args);
    }
}

相关问题