Faizy
Faizy

Reputation: 297

Efficient way to display different views/layouts/content with JavaFX

I have a menu which should be used to navigate through different "views"(layout). The menu should always be visible. The only thing that should change is the displayed content, in dependency of the selected menu item.

I have a very basic example, using two classes, created below:

public class Main extends Application{

    static final Pane pane = new Pane();

    public void start(Stage stage) {
        pane.getChildren().addAll(Menu.getPaneMenu());
        Scene scene = new Scene(pane);
        stage.setScene(scene);
        stage.setMaximized(true);
        stage.show();
    }

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

public class Menu {
    private static final Pane paneMenu = new Pane();

    static Pane getPaneMenu() {
        Button btn1 = new Button("Menu 1");
        btn1.relocate(100, 10);
        btn1.setPrefSize(100, 20);
        btn1.setOnAction(e -> {
            Label lbl = new Label("You clicked Menu1");
            lbl.relocate(200, 40);
            Main.pane.getChildren().add(lbl);
        });


        Button btn2 = new Button("Menu 2");
        btn2.relocate(300, 10);
        btn2.setPrefSize(100, 20);
        btn2.setOnAction(e -> {
            Label lbl = new Label("You clicked Menu2");
            lbl.relocate(200, 40);
            Main.pane.getChildren().add(lbl);
        });
        paneMenu.getChildren().addAll(btn1, btn2);

        return paneMenu;
    }
}

The challenge I´m facing is, that when clicking a menu, the old menu stays(as you can see, the displayed text overwrites the other): enter image description here

What would be an efficient way to solve this overlapping?

Upvotes: 2

Views: 1412

Answers (2)

SedJ601
SedJ601

Reputation: 13858

Here is an example that shows how to load two different Panes in a BorderPane.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Sample extends Application {

    @Override public void start(Stage stage) {

        BorderPane root = new BorderPane();        

        Button loadSceneOne = new Button("Load Scene One");
        //Event hanlder to load scene one
        loadSceneOne.setOnAction((event)->{
            root.setCenter(getSceneOne());
        });

        //Event hanlder to load scene two
        Button loadSceneTwo = new Button("Load Scene Two");
        loadSceneTwo.setOnAction((event)->{
            root.setCenter(getSceneTwo());
        });

        VBox menu = new VBox();
        menu.getChildren().addAll(loadSceneOne, loadSceneTwo);

        root.setLeft(menu);       

        Scene scene = new Scene(root);   
        stage.setMaximized(true);
        stage.setScene(scene);
        stage.show();
    }

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

    //Scene One
    Pane getSceneOne()
    {
        Pane pane = new Pane();

        Label label = new Label("Scene One!");
        StackPane stackPane = new StackPane();
        stackPane.getChildren().add(label);

        pane.getChildren().add(stackPane);

        return pane;
    }

    //Scene Two
    Pane getSceneTwo()
    {
        Pane pane = new Pane();

        Label label = new Label("Scene Two!");
        StackPane stackPane = new StackPane();
        stackPane.getChildren().add(label);

        pane.getChildren().add(stackPane);

        return pane;
    }

}

Upvotes: 1

What about declaring labels as fields of the Menu class (same with buttons)? Then you can add/remove them from the pane. I modified your code a little - it should works in this particular case:

class Menu {
  private static final Pane paneMenu = new Pane();
  private static final Button btn1 = new Button("Menu 1");
  private static final Button btn2 = new Button("Menu 2");
  private static final Label firstLabel = new Label("You clicked Menu1");
  private static final Label secondLabel = new Label("You clicked Menu2");

  static Pane getPaneMenu() {
    ObservableList<Node> mainPaneChildren = Main.pane.getChildren();

    btn1.relocate(100, 10);
    btn1.setPrefSize(100, 20);
    btn1.setOnAction(e -> {
      firstLabel.relocate(200, 40);
      if (mainPaneChildren.contains(secondLabel)) {
        mainPaneChildren.remove(secondLabel);
      }
      if (!mainPaneChildren.contains(firstLabel)) {
        mainPaneChildren.add(firstLabel);
      }
    });


    btn2.relocate(300, 10);
    btn2.setPrefSize(100, 20);
    btn2.setOnAction(e -> {
      secondLabel.relocate(200, 40);
      if (mainPaneChildren.contains(firstLabel)) {
        mainPaneChildren.remove(firstLabel);
      }
      if (!mainPaneChildren.contains(secondLabel)) {
        mainPaneChildren.add(secondLabel);
      }
    });
    paneMenu.getChildren().addAll(btn1, btn2);

    return paneMenu;
  }
}

If there are going to be more elements than just a Label it would be better if you put them in some kind of a Pane. Than you can add/remove that Pane. By the way - have a look at Working With Layouts in JavaFX? I don't think that using relocate() is a good practice.

Upvotes: 0

Related Questions