0

I have two separate views one which contains a button say view A and another a TabPane with 3 tabs call it view B. These two views are controlled by two separate view controller classes. I want to be able to click a button in view A and be able to to open a specific tab in view B's TabPane.

So far I have tried extending the controller for view A with view B such that I can get the TabPane defined in view B's controller then call myTabPane.getSelectionModel().select(myTab); however this hasn't worked as it throws a NullPointerException.

My question is it possible to click a button in view A such that it opens view B and opens a specific Tab on view B's TabPane.

I have also looked at these links with no luck 1. setting selected tab, 2. switch through tabs programatically, 3. switch between tabs in tabpane

view A

Lets say the above image is view A and when u click right it should open view B and open a specific tab in view B's TabPane.

view B

Lets say the above image is view B and when the button right on view A is clicked it should open view B and set the tab to tab C.

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.control.SelectionModel;

public class SucessfulCreateProjectViewController extends AdminViewController {


 @FXML
 private Button OkButton;

@FXML
void handleCreateTasksButtonAction(ActionEvent event) {


try{
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setLocation(getClass().getResource("AdminView.fxml"));
    Scene scene = new Scene(fxmlLoader.load());
    Stage stage = new Stage();
    stage.setScene(scene);
    stage.show();
    AdminTabPane.getSelectionModel().select(1);; 

   }catch(Exception e){

    ErrorHandlerController.infoBox("Error Opening AdminPage", "Fail", null);
    e.printStackTrace();
   }

}

@FXML
void handleOKButtonAction(ActionEvent event) {

  Stage stage = (Stage) OkButton.getScene().getWindow();
  stage.close();

}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    }
DvixExtract
  • 1,275
  • 15
  • 25

1 Answers1

2

Mediator is a design pattern that is used to communicate between objects that do not know each other.

This is an example of a mediator that would have done your job.

public class Mediator {
    private static Mediator instance;

    private Consumer<String> consumer;

    public static Mediator getInstance() {
        if(instance == null) {
            instance = new Mediator();
        }
        return instance;
    }

    private Mediator() {
    }

    public void register(Consumer<String> consumer) {
        this.consumer = consumer;
    }

    public void fireEvent(String string) {
        if(consumer != null) {
            consumer.accept(string);
        }
    }
}

and respectively, the two controllers

public class ViewAController {
    @FXML
    private Button btnL, btnR;

    @FXML
    private void initialize() {
        btnL.setOnAction(event -> Mediator.getInstance().fireEvent("left"));
        btnR.setOnAction(event -> Mediator.getInstance().fireEvent("right"));
    }
}

public class ViewBController {

    @FXML
    private TabPane tabPane;

    @FXML
    private void initialize() {
        Mediator.getInstance().register(s -> {
            switch (s) {
                case "left":
                    tabPane.getSelectionModel().select(0);
                    break;

                case "right":
                    tabPane.getSelectionModel().select(2);
                    break;
            }
        });
    }
}

and this is a test application that opens two windows at once.

public class Main extends Application {

    @Override
    public void start(Stage stageA) throws Exception{
        Parent viewA = FXMLLoader.load(getClass().getResource("view_a.fxml"));
        Parent viewB = FXMLLoader.load(getClass().getResource("view_b.fxml"));

        stageA.setTitle("View A");
        stageA.setScene(new Scene(viewA));
        stageA.show();

        Stage stageB = new Stage();
        stageB.setTitle("View B");
        stageB.setScene(new Scene(viewB));
        stageB.show();
    }


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

if you do not want to use two windows at once, just change the middleman.

mr mcwolf
  • 2,574
  • 2
  • 14
  • 27