繁体   English   中英

如何在 JavaFX 中的所有场景中显示菜单栏

[英]How do i display my MenuBar across all my scenes in JavaFX

我是 JavaFX 的新手

但是我写了这段代码,我不知道如何在我的所有场景中显示菜单栏。 此外,我想在我的 HelloApplication 中使用布局创建/填充我的场景(但那是另一个问题)。

我有一个控制器,用于设置舞台并启动它。 我的 MenuBar 在 MenuLeiste 类中,但我希望它也出现在我的 Credits 类中。 对于缺少评论和此评论的布局,我感到非常抱歉。

    
    public class HelloApplication extends Application {

    public class Main {
    public static void main(String[] args) {
        launch(args);
    }
    }

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

    //set window as primaryStage
    Stage window = primaryStage;


    //Layout of MenuLeiste is put in l1 and setted as scene1
    MenuLeiste l1 = new MenuLeiste();
    //menuscene gets its objects fromsceneViewMenu
    Scene menuscene = new Scene(l1.sceneViewMenu());

    window.setScene(menuscene);

    window.setHeight(600);
    window.setWidth(800);
    window.setTitle("Game Title");
    window.show();
    }
    }

我的 MenuLeiste 课程

    import javafx.scene.Scene;
    import javafx.scene.control.Menu;
    import javafx.scene.control.MenuBar;
    import javafx.scene.control.MenuItem;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;


    public class MenuLeiste {

        public VBox sceneViewMenu() {

        MenuBar menuBar = new MenuBar();
        VBox menuBox = new VBox(menuBar);

        Menu dataMenu = new Menu("Data");
                MenuItem exitItem = new MenuItem("Exit");
                exitItem.setOnAction(e -> System.exit(0));

        Menu extrasMenu = new Menu("Extras");
                MenuItem creditsItem = new MenuItem("Credits");
                creditsItem.setOnAction(e -> {
                        Credits c = new Credits();
                        Scene scene3 = new Scene(c.sceneView3());
                        Stage window = (Stage) menuBox.getScene().getWindow();
                        window.setScene(scene3);
                        });
        

        extrasMenu.getItems().addAll(creditsItem);
        dataMenu.getItems().addAll( exitItem);


        menuBar.getMenus().addAll(dataMenu,extrasMenu);

            //the scenes layout is saved in layout1
            VBox layout1 = new VBox(20);
            layout1.getChildren().addAll(menuBox);
        
            return layout1;
        }
        }

我的学分课程

package view;

import javafx.scene.Scene;`
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;`



public class Credits {
    public VBox sceneView3() 
    {

    Label label = new Label("Thanks");
    Button backButton = new Button("Back");

    backButton.setOnAction(e -> {
        MenuLeiste l1 = new MenuLeiste();
        Scene menuscene = new Scene(l1.sceneViewMenu());
        Stage window = (Stage) backButton.getScene().getWindow();
        window.setScene(menuscene);
    });
    
    VBox layout1 = new VBox(20);
    layout1.getChildren().addAll(label, backButton);
    
    return layout1;
    }
    }

当您希望一个节点或一组节点存在于不同的“场景”之间时,通常最好的解决方案是替换Scene 相反,您需要修改当前场景中显示的节点。 例如,在您的情况下,您可以将BorderPane作为场景的根,并将MenuBar设置为top节点。 然后,当您要更改“视图”时替换center节点。

这是一个演示此概念的最小可运行示例。 它使用“回调”来修改BorderPane的中心节点,同时始终使用相同的MenuBar实例。 尽管请注意该示例仅包含视图。 如果您有一个支持模型(即数据、业务逻辑等),您将需要修改代码以便可以传递它。 此外,如果您编写的应用程序与此示例类似,那么让所有视图在实际应用程序中实现一个公共接口可能是明智的。

我没有单独的菜单栏“视图类”,但这并不意味着你不能拥有一个(这样可能会更好)。

主.java

import java.util.function.Consumer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    var root = new BorderPane();
    root.setTop(createMenuBar(root::setCenter));
    root.setCenter(new TitleView().getNode());

    primaryStage.setScene(new Scene(root, 600, 400));
    primaryStage.setTitle("Demo");
    primaryStage.show();
  }

  private MenuBar createMenuBar(Consumer<Node> onUpdateView) {
    var exitItem = new MenuItem("Exit");
    exitItem.setOnAction(e -> Platform.exit());

    var creditsItem = new MenuItem("Credits");
    creditsItem.setOnAction(e -> {
      e.consume();

      var view = new CreditsView();
      view.setOnGoBack(() -> onUpdateView.accept(new TitleView().getNode()));
      onUpdateView.accept(view.getNode());
    });

    return new MenuBar(
        new Menu("File", null, exitItem),
        new Menu("Extras", null, creditsItem)
    );
  }
}

标题视图.java:

import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;

public class TitleView {

  private Node node;

  public Node getNode() {
    if (node == null) {
      node = new StackPane(new Label("Welcome!"));
    }
    return node;
  }
}

CreditsView.java:

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;

public class CreditsView {

  private Runnable onGoBack;
  private Node node;

  public Node getNode() {
    if (node == null) {
      var stack = new StackPane();
      stack.setPadding(new Insets(10));

      var label = new Label("Credits View");
      stack.getChildren().add(label);

      var goBackBtn = new Button("Go back");
      goBackBtn.setOnAction(e -> {
        e.consume();
        if (onGoBack != null) {
          onGoBack.run();
        }
      });
      stack.getChildren().add(goBackBtn);
      StackPane.setAlignment(goBackBtn, Pos.TOP_LEFT);

      node = stack;
    }
    return node;
  }

  public void setOnGoBack(Runnable action) {
    onGoBack = action;
  }
}

以下是一些初学者应该很容易理解的基本代码。

  1. 主要布局和要在其中显示的潜在视图是预先创建的。

  2. 菜单栏位于主布局中边框窗格的顶部。

  3. 通过将节点设置为当前显示在边框窗格的中心,可以使用菜单项在视图之间切换。

  4. 现有视图被重用,而不是在每个导航上重新创建。

    • 如果愿意,您不能存储对现有视图的引用并在每个导航上创建新视图。

视图本身只是节点,因此该示例可以很容易地适应使用 FXML,因为 FXML 加载器的输出也是一个节点。 这同样适用于任何其他可能生成以这种方式用作视图的节点的东西。

手术

最初显示场景,用户单击“视图”菜单以显示可用视图的列表。

查看一个

用户选择“查看二”菜单项并显示第二个视图。 应用程序菜单仍然可见,可用于将来的操作。

查看二

示例代码

import javafx.application.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class ViewSwitcherApp extends Application {
    private BorderPane layout;
    private final Node viewOne = new ViewOne();
    private final Node viewTwo = new ViewTwo();

    @Override
    public void start(Stage stage) throws Exception {
        // View menu
        MenuItem viewOneMenuItem = new MenuItem("View One");
        viewOneMenuItem.setOnAction(e -> setView(viewOne));
        MenuItem viewTwoMenuItem = new MenuItem("View Two");
        viewTwoMenuItem.setOnAction(e -> setView(viewTwo));
        Menu viewMenu = new Menu(
                "View", null,
                viewOneMenuItem, viewTwoMenuItem
        );

        // File menu
        MenuItem exitMenuItem = new MenuItem("Exit");
        exitMenuItem.setOnAction(e -> Platform.exit());
        Menu fileMenu = new Menu(
                "File", null,
                exitMenuItem
        );

        MenuBar menuBar = new MenuBar(
                fileMenu, viewMenu
        );
        menuBar.setMinSize(MenuBar.USE_PREF_SIZE, MenuBar.USE_PREF_SIZE);

        // Layout scene
        layout = new BorderPane();
        layout.setTop(menuBar);
        setView(viewOne);

        stage.setScene(
                new Scene(layout, 300, 200)
        );
        stage.show();
    }

    private void setView(Node view) {
        layout.setCenter(view);
    }

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

class ViewOne extends StackPane {
    public ViewOne() {
        setStyle("-fx-background-color: lightblue; -fx-font-size: 30px;");
        getChildren().add(new Label("View One"));
    }
}

class ViewTwo extends StackPane {
    public ViewTwo() {
        setStyle("-fx-background-color: cornsilk; -fx-font-size: 30px;");
        getChildren().add(new Label("View Two"));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM