0

My goal is to change center Pane in my main window of programm controlled by one controller by actions on buttons in different controller. I know i have to instantiate main window controller in other controller in order to access main window view, and i know that i can Autowire (inject) main controller class into different controller, but when i do this i get all my Css styling and main menu inactive, and without it i get Nullpointer exception when i try to use MainController from MainMenuController

i have main.fxml


<?import com.jfoenix.controls.JFXDrawer?>
<?import com.jfoenix.controls.JFXHamburger?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.StackPane?>

<StackPane fx:id="rootPane" prefHeight="720.0" prefWidth="1280.0" styleClass="root" stylesheets="@../style/dark-theme-contrast.css" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hrc.backoffice.MainController">
   <children>
      <AnchorPane accessibleRole="MENU_BUTTON" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" styleClass="root" stylesheets="@../style/dark-theme-contrast.css">
         <children>
            <BorderPane prefHeight="720.0" prefWidth="1280.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
               <left>
                  <JFXDrawer fx:id="mainMenuDrawer" alignment="CENTER_LEFT" defaultDrawerSize="220.0" prefWidth="0.0" resizableOnDrag="true" stylesheets="@../style/dark-theme-contrast.css" BorderPane.alignment="TOP_LEFT" />
               </left>
               <center>
                  <AnchorPane fx:id="mainWindowCenterPane" BorderPane.alignment="TOP_LEFT">
                     <children>
                        <JFXHamburger fx:id="mainMenuHamburger" styleClass="jfx-hamburger-icon" stylesheets="@../style/dark-theme-contrast.css" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0" />
                     </children>
                  </AnchorPane>
               </center>
            </BorderPane>
         </children>
      </AnchorPane>
   </children>

this is MainController.java

public class MainController implements Initializable {

    @FXML
    private StackPane rootPane;

    @FXML
    private JFXDrawer mainMenuDrawer;

    @FXML
    private JFXHamburger mainMenuHamburger;


    @FXML
    private AnchorPane mainWindowCenterPane;

    
    @Override
    public void initialize(URL location, ResourceBundle resources) {

        try {
            initDrawer();
        } catch (IOException e) {
            e.printStackTrace();
            Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, e);
        }
    }


    private void initDrawer() throws IOException {
        ScrollPane menuScrollpane = FXMLLoader.load(getClass().getResource("/view/mainMenu.fxml"));
        mainMenuDrawer.setSidePane(menuScrollpane);

        HamburgerSlideCloseTransition task = new HamburgerSlideCloseTransition(mainMenuHamburger);
        task.setRate(-1);
        mainMenuHamburger.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
            mainMenuDrawer.toggle();
        });

        mainMenuDrawer.setOnDrawerOpening((event) -> {
            task.setRate(task.getRate() * -1);
            task.play();
            mainMenuDrawer.setMinWidth(220);
        });
        mainMenuDrawer.setOnDrawerClosed((event) -> {
            task.setRate(task.getRate() * -1);
            task.play();
            mainMenuDrawer.setMinWidth(0);
        });
    }

    public void setMainWindowCenterPane(AnchorPane mainWindowCenterPane) {
        this.mainWindowCenterPane = mainWindowCenterPane;
    }
    
}

here is main-menu.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import com.jfoenix.controls.JFXButton?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<ScrollPane fx:id="mainMenuScrollPane" prefHeight="720.0" prefWidth="220.0" stylesheets="@../style/dark-theme-contrast.css" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hrc.backoffice.MainMenuController">
   <content>
      <VBox fx:id="mainMenuVbox" prefHeight="574.0" prefWidth="200.0" stylesheets="@../style/dark-theme-contrast.css">
         <children>
            <Accordion fx:id="mainMenuAccordion" stylesheets="@../style/dark-theme-contrast.css">
               <panes>
                  
                  <TitledPane fx:id="menuProductMenu" alignment="TOP_RIGHT" contentDisplay="RIGHT" expanded="false" nodeOrientation="RIGHT_TO_LEFT" stylesheets="@../style/dark-theme-contrast.css" text="Меню">
                     <graphic>
                        <ImageView fitHeight="25.0" fitWidth="25.0" pickOnBounds="true" preserveRatio="true">
                           <image>
                              <Image url="@../images/028-menu1.png" />
                           </image>
                        </ImageView>
                     </graphic>
                     <content>
                        <VBox prefHeight="100.0" prefWidth="216.0" styleClass="titled-pane" stylesheets="@../style/dark-theme-contrast.css">
                           <children>
                              <JFXButton fx:id="compositeProductMenu" alignment="BASELINE_RIGHT" buttonType="RAISED" onAction="#initCompositeProductMenu" prefHeight="30.0" prefWidth="170.0" text="Блюда" textFill="WHITE">
                                 <font>
                                    <Font size="13.0" />
                                 </font>
                              </JFXButton>
                              <JFXButton fx:id="semifinishedProductMenu" alignment="BASELINE_RIGHT" buttonType="RAISED" layoutX="20.0" layoutY="20.0" prefHeight="30.0" prefWidth="170.0" text="Полуфабрикаты" textFill="WHITE">
                                 <font>
                                    <Font size="13.0" />
                                 </font>
                              </JFXButton>
                              <JFXButton fx:id="compositeProductMenuCategories" alignment="BASELINE_RIGHT" buttonType="RAISED" layoutX="20.0" layoutY="45.0" prefHeight="30.0" prefWidth="170.0" text="Категории блюд" textFill="WHITE">
                                 <font>
                                    <Font size="13.0" />
                                 </font>
                              </JFXButton>
                              <JFXButton fx:id="productModificators" alignment="BASELINE_RIGHT" buttonType="RAISED" layoutX="10.0" layoutY="60.0" prefHeight="30.0" prefWidth="170.0" text="Модификаторы" textFill="WHITE">
                                 <font>
                                    <Font size="13.0" />
                                 </font>
                              </JFXButton>
                           </children>
                        </VBox>
                     </content>
                     <font>
                        <Font name="System Bold Italic" size="14.0" />
                     </font>
                  </TitledPane>
                  
               </panes>
            </Accordion>
         </children>
      </VBox>
   </content>

and MainMenuController.java

public class MainMenuController  implements Initializable {

    @FXML
    private ScrollPane mainMenuScrollPane;

    @FXML
    private VBox mainMenuVbox;

    @FXML
    private Accordion mainMenuAccordion;

    @FXML
    private TitledPane menuFinances;

    @FXML
    private TitledPane menuProductMenu;

    @FXML
    private JFXButton compositeProductMenu;

    @FXML
    private JFXButton semifinishedProductMenu;

    @FXML
    private JFXButton compositeProductMenuCategories;

    @FXML
    private JFXButton productModificators;

    @FXML
    private TitledPane menuStock;

    @FXML
    private TitledPane menuProductOperations;

    @FXML
    private TitledPane menuMarketing;

    @FXML
    private TitledPane menuCompany;

    @FXML
    private TitledPane menuStatistics;

    @FXML
    private TitledPane menuSettings;

    MainController mainController;

//    @Autowired
//    public MainMenuController(MainController mainController) {
//        this.mainController = mainController;
//    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        initCompositeProductMenu();
//        compositeProductMenu.setOnAction(event -> {
//            try {
//                AnchorPane productMenuPane = FXMLLoader.load(getClass().getResource("/view/product-menu-list.fxml"));
//                mainController.setMainWindowCenterPane(productMenuPane);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        });
    }



    @FXML
    private void initCompositeProductMenu() {

        compositeProductMenu.addEventHandler(ActionEvent.ACTION, event1 -> {
            try {
                AnchorPane productMenuPane = FXMLLoader.load(getClass().getResource("/view/product-menu-list.fxml"));
                mainController.setMainWindowCenterPane(productMenuPane);
            } catch (IOException e) {
                e.printStackTrace();
            }

        });

    }

}

and the view i want to pass to main window in product-menu-list.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import com.jfoenix.controls.JFXTabPane?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="720.0" prefWidth="1200.0" stylesheets="@../style/dark-theme-contrast.css" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hrc.backoffice.ProductMenuListController">
   <children>
      <JFXTabPane prefHeight="720.0" prefWidth="1200.0" stylesheets="@../style/dark-theme-contrast.css" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <tabs>
            <Tab text="Untitled Tab">
              <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                     <children>
                        <TableView prefHeight="691.2000202824526" prefWidth="1200.0000352125912" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                          <columns>
                            <TableColumn prefWidth="75.0" text="C1" />
                            <TableColumn prefWidth="75.0" text="C2" />
                              <TableColumn prefWidth="75.0" text="C1" />
                              <TableColumn prefWidth="75.0" text="C2" />
                          </columns>
                           <columnResizePolicy>
                              <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                           </columnResizePolicy>
                           <padding>
                              <Insets top="5.0" />
                           </padding>
                        </TableView>
                     </children>
                  </AnchorPane>
              </content>
            </Tab>
            <Tab text="Untitled Tab">
              <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
              </content>
            </Tab>
            <Tab text="Untitled Tab">
              <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
              </content>
            </Tab>
         </tabs>
      </JFXTabPane>
   </children>
</AnchorPane>

I know i have to instantiate main window controller in other controller in order to access main window view, and i know that i can Autowire (inject) main controller class into different controller, but when i do this i get all my Css styling and main menu inactive, and without it i get Nullpointer exception when i try to use MainController from MainMenuController of course.

what i get with @Autowired // public MainMenuController(MainController mainController) { // this.mainController = mainController; // }

is Complitelly inactive white window with only Hamburger widget visible but inactive

What am i missing???

Project Structure

Effect

Roman_G
  • 11
  • 3
  • 1
    This is really a design issue. You really want a new controller instance each time you load any given FXML file, so your controllers should have prototype scope. On the other hand, if you do that, you won’t have a reference to the controller instance you want in the other controller. It’s just generally a bad idea for one controller to have a reference to another, as it introduces unnecessary coupling. Consider using a MVC approach instead, so you can inject a single model instance into any controller that needs it. See https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx – James_D Feb 12 '21 at 12:45
  • @James_D already nailed the problem - as always :) For your next question, please provide a [mcve] (vs. the complete near-production thing which contains tons of unrelated code to wade through) – kleopatra Feb 12 '21 at 14:27
  • Note also your `setMainWindowCenterPane(...)` doesn't actually do anything to the UI. You would need something like `rootPane.getChildren().setAll(mainWindowCenterPane)`. – James_D Feb 12 '21 at 15:46
  • Thank you @James_D for quick response, i will dig into that direction – Roman_G Feb 12 '21 at 16:45

0 Answers0