0

I know that there are a lot of questions already answered for this, but I just cant get my head around it. It is a possible duplicate of:

accessing a Pane from another class in javafx

JavaFX change Pane color from a different class

In my app I want to clear the changablePane (StackPane) in the MainWindowController from a mouseEvent in the NotesScreenController so that only the marked as done notes will be displayed.

MainWindowController.java

package gui;

import gui.mainWindow.issues.NotesScreenController;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Stack;

public class MainWindowController implements Initializable {

    private Stage stage = null;
    private StackPane paneNotes = null;
    private NotesScreenController secondPane;

    @FXML
    private AnchorPane mainContainer;

    @FXML
    private VBox vBoxContainer;

    @FXML
    private MenuBar menuBarTop;

    @FXML
    private HBox hBoxContainer;

    @FXML
    private StackPane navigationSection;

    @FXML
    private TreeView<Button> treeView;

    @FXML
    private StackPane changablePane;

    public static Button issuesNotes;


    //TAB SO FILTRI
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        createTreeView();
    }

    private void createTreeView()   {
        Button treeViewHeader = new Button("Zdravo");
        TreeItem<Button> treeViewHeaderItem = new TreeItem<>(treeViewHeader);
        treeViewHeader.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");
        treeViewHeaderItem.setExpanded(true);
        //ROOT FOR ISSUES TRACKING
        Button rootForIssues = new Button("Issues Tracker");
        Button issuesTable = new Button("Issues Table");
        issuesNotes = new Button("Request Notes");
        TreeItem<Button> rootForIssuesItem = new TreeItem<>(rootForIssues);
        TreeItem<Button> issuesTableItem = new TreeItem<>(issuesTable);
        TreeItem<Button> issuesNotesItem = new TreeItem<>(issuesNotes);

        rootForIssues.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");
        issuesTable.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");
        issuesNotes.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");

        rootForIssuesItem.setExpanded(true);
        rootForIssuesItem.getChildren().addAll(issuesTableItem, issuesNotesItem);

        //ROOT ZA NEKOE DRUGO - PROBNO
        Button buttonA = new Button("Proba");
        Button buttonB = new Button("Proba");
        Button buttonC = new Button("Proba");
        TreeItem<Button> nodeA = new TreeItem<>(buttonA);
        TreeItem<Button> nodeB = new TreeItem<>(buttonB);
        TreeItem<Button> nodeC = new TreeItem<>(buttonC);

        buttonA.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");
        buttonB.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");
        buttonC.getStylesheets().add("styles/Notes/TreeViewStyles/TreeButton.css");

        nodeA.setExpanded(true);
        nodeA.getChildren().addAll(nodeB, nodeC);

        //ADDING ALL ROOTs OF THE TREEVIEW
        treeViewHeaderItem.getChildren().addAll(rootForIssuesItem, nodeA);

        issuesNotes.setOnAction(event ->{
            clearPane();
            URL paneOneUrl = getClass().getClassLoader().getResource("gui/mainWindow/issues/NotesScreen.fxml");
            FXMLLoader loader = new FXMLLoader();
            NotesScreenController nsc = new NotesScreenController();
            loader.setController(nsc);
            try {
                paneNotes = loader.load(paneOneUrl);
                changablePane.getChildren().add(paneNotes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        issuesTable.setOnAction(event ->    {
            clearPane();
        });

        //TREE VIEW
        treeView.setId("tree-view-issues");
        treeView.getStylesheets().addAll("styles/Notes/TreeViewStyles/TreeView.css");
        treeView.setRoot(treeViewHeaderItem);
    }

    public void clearPane()  {
        changablePane.getChildren().clear();
    }

    public void getMainScreenController()   {

    }

    public static Button getIssuesNotes()   {
        return issuesNotes;
    }

    public void setStage(Stage stage)   {
        this.stage = stage;
        stage.setResizable(true);
        stage.setTitle("SoloStats - Welcome");
    }

    public void closeStage()    {
        if (this.stage != null) {
            this.stage.close();
        }
    }
}

MainWindow.fxml

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>

<AnchorPane fx:id="mainContainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.MainWindowController">
   <children>
      <VBox fx:id="vBoxContainer" layoutX="530.0" layoutY="230.0" prefHeight="25.0" prefWidth="1200.0" AnchorPane.bottomAnchor="572.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <MenuBar fx:id="menuBarTop" prefHeight="25.0">
              <menus>
                <Menu mnemonicParsing="false" text="File">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Close" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Edit">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Delete" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Help">
                  <items>
                    <MenuItem mnemonicParsing="false" text="About" />
                  </items>
                </Menu>
              </menus>
            </MenuBar>
         </children>
      </VBox>
      <HBox fx:id="hBoxContainer" layoutX="384.0" layoutY="238.0" prefHeight="600.0" prefWidth="1200.0" style="-fx-background-color: rgb(247, 247, 247);" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="25.0">
         <children>
            <StackPane fx:id="navigationSection" prefHeight="150.0" prefWidth="300.0" style="-fx-background-color: #222;">
               <children>
                  <TreeView fx:id="treeView" fixedCellSize="24.0" prefHeight="200.0" prefWidth="200.0">
                     <StackPane.margin>
                        <Insets left="-25.0" />
                     </StackPane.margin>
                  </TreeView>
               </children>
            </StackPane>
            <StackPane fx:id="changablePane" prefHeight="575.0" prefWidth="950.0" stylesheets="@../styles/MainWindow/StackPaneChangable.css" HBox.hgrow="ALWAYS" />
         </children>
      </HBox>
   </children>
</AnchorPane>

NotesScreenController.java

package gui.mainWindow.issues;

import gui.MainWindowController;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class NotesScreenController extends AnchorPane implements Initializable {
    private NotesDirectory notesDirectory = new NotesDirectory();
    private MainWindowController mainController;

    @FXML
    private StackPane mainContainer;

    @FXML
    private VBox vBoxContainer;

    @FXML
    private HBox hBoxFilterContainer;

    @FXML
    private ScrollPane scrollPane;

    @FXML
    private TilePane tilePaneNotesScreen;

    @FXML
    private ComboBox<String> generalSortBox;

    @FXML
    private ComboBox<String> sortByNameBox;

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

    public void loadScreen()    {
        try {
            notesDirectory.insertNotesToTilePane(tilePaneNotesScreen, notesDirectory.deserializedNotesList(notesDirectory.getFileName(new File("src/notesDirectory")), "src/notesDirectory/"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        generalSortBox.setItems(FXCollections.observableArrayList("Flagged", "Date added", "Done Notes"));
        sortByNameBox.setItems(FXCollections.observableArrayList("Priority", "Priority", "Priority", "Priority",
                "Priority", "Priority", "Priority", "Priority", "Priority", "Priority", "Priority", "Priority",
                "Priority", "Priority"));
        generalSortBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> selected, String oldValue, String newValue) {
                if (newValue != null)   {
                    switch (newValue)   {
                        case "Done Notes": try {
                            //THE ACTION NEED TO TAKE PLACE HERE
                            notesDirectory.insertNotesToTilePane(tilePaneNotesScreen, notesDirectory.deserializedNotesList(notesDirectory.getFileName(new File("src/notesRecycleBin")), "src/notesRecycleBin/"));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
    }

    public void setMainController(MainWindowController controller) {
        this.mainController = controller;
    }
}

NotesScreen

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.TilePane?>
<?import javafx.scene.layout.VBox?>


<StackPane fx:id="mainContainer" prefHeight="575.0" prefWidth="950.0" stylesheets="@../../../styles/MainWindow/StackPaneChangable.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.mainWindow.issues.NotesScreenController">
   <children>
      <VBox fx:id="vBoxContainer" prefHeight="575.0" prefWidth="950.0">
         <children>
            <HBox fx:id="hBoxFilterContainer" stylesheets="@../../../styles/MainWindow/ChoiceBox/HBoxFilters.css">
               <children>
                  <ComboBox fx:id="generalSortBox" prefHeight="25.0" prefWidth="220.0" promptText="Sort by..." stylesheets="@../../../styles/MainWindow/ChoiceBox/ComboBox.css" />
                  <ComboBox fx:id="sortByNameBox" prefHeight="25.0" prefWidth="220.0" promptText="Choose name" stylesheets="@../../../styles/MainWindow/ChoiceBox/ComboBox.css" />
               </children>
            </HBox>
            <ScrollPane fx:id="scrollPane" fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER" prefHeight="575.0" prefWidth="950.0" stylesheets="@../../../styles/MainWindow/StackPaneChangable.css" VBox.vgrow="ALWAYS">
               <content>
                  <TilePane fx:id="tilePaneNotesScreen" hgap="25.0" prefColumns="4" prefHeight="575.0" prefTileWidth="228.0" prefWidth="950.0" stylesheets="@../../../styles/MainWindow/StackPaneChangable.css" vgap="25.0">
                     <padding>
                        <Insets bottom="25.0" left="25.0" right="25.0" top="35.0" />
                     </padding>
                  </TilePane>
               </content>
            </ScrollPane>
         </children>
      </VBox>
   </children>
</StackPane>
ejfilip
  • 75
  • 2
  • 10
  • Make the MainWindowController a singleton class and create a public method in the MainWindowController class which clears the pane. Then call that method from the NotesScreenController class by getting the singleton instance from MainWindowController Class. – IR Emon Sep 29 '17 at 11:06
  • Whatever you do, do **not** make the controller a singleton. If you load multiple copies of the FXML file, the fields in the controller will be referring to the wrong thing (if you load multiple copies of the FXML, you need multiple instances of the controller). – James_D Sep 29 '17 at 12:07
  • 1
    Your problem (one problem: I haven't read all the code yet) is in how you load the FXML file: `paneNotes = loader.load(paneOneUrl)` calls the **static** [`FXMLLoader.load(URL)`](https://docs.oracle.com/javase/9/docs/api/javafx/fxml/FXMLLoader.html#load-java.net.URL-) method. Since it's a static method, it's not invoked on the `FXMLLoader` instance you created, and so the previous call to `setController(...)` is effectively ignored. You need `loader.setLocation(paneOneUrl);` and then `paneNotes = loader.load();`. You also need to remove `fx:controller="..."` from `NotesScreen.fxml`. – James_D Sep 29 '17 at 12:11

1 Answers1

0

Basically all you are missing is setting the main screen controller in the NotesScreenController instance:

FXMLLoader loader = new FXMLLoader();
NotesScreenController nsc = new NotesScreenController();
loader.setController(nsc);

nsc.setMainController(this);

And then from the NotesScreenController you can clear the pane simply by calling

mainController.clearPane();

i.e. you can do:

generalSortBox.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> selected, String oldValue, String newValue) {
        if (newValue != null)   {
            switch (newValue)   {
                case "Done Notes": try {
                    //THE ACTION NEED TO TAKE PLACE HERE
                    mainController.clearPane();
                    notesDirectory.insertNotesToTilePane(tilePaneNotesScreen, notesDirectory.deserializedNotesList(notesDirectory.getFileName(new File("src/notesRecycleBin")), "src/notesRecycleBin/"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
});

Note you have one subtle bug: when you call

paneNotes = loader.load(paneOneUrl); 

you are calling the static FXMLLoader.load(URL) method. Since it's a static method, it's not invoked on the FXMLLoader instance you created, and so the previous call to setController(...) is effectively ignored. You need to set the location of the FXMLLoader instance, and then call the no-arg load() method. So you should have:

issuesNotes.setOnAction(event ->{
    clearPane();
    URL paneOneUrl = getClass().getClassLoader().getResource("gui/mainWindow/issues/NotesScreen.fxml");
    FXMLLoader loader = new FXMLLoader();
    NotesScreenController nsc = new NotesScreenController();
    nsc.setMainController(this);
    loader.setController(nsc);
    loader.setLocation(paneOneUrl);
    try {
        // note call to no-arg load() method:
        paneNotes = loader.load();
        changablePane.getChildren().add(paneNotes);
    } catch (IOException e) {
        e.printStackTrace();
    }
});

Finally, since you are setting the controller from the Java code, you need to remove the fx:controller attribute from the NotesScreen.fxml root element:

<StackPane fx:id="mainContainer" prefHeight="575.0" prefWidth="950.0" stylesheets="@../../../styles/MainWindow/StackPaneChangable.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">

    <!-- ... -->

</StackPane>
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Hi James_D, thanks for the answer. About the first part - I can't call nsc.setMainController because the method has a MainScreenController in the parametar. I also tried to fix the bug, but after editing the code like you suggested the NotesScreenCotroller is never initialized, the screen only shows the elements of the fxml file – ejfilip Sep 29 '17 at 20:34
  • if you think that i should have a different approach in structuring my app in order to get this going, please let me know. I would really appreciate it. – ejfilip Sep 30 '17 at 19:17