How to make that when i click on "Open second window" the main window be hide. And when i close second window, the main window be showed? I read this post, but i don't know how to implement it for my task. Thanks!
I have next code:
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("First Stage");
try {
primaryStage.setResizable(false);
Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
MainWiew.fxml
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane id="rootMain" prefHeight="418.0" prefWidth="691.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.view.MainController">
<top>
</top>
<center>
<AnchorPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<VBox fillWidth="false" prefHeight="400.0" prefWidth="394.0" spacing="8.0">
<children>
<Button id="btnMainOne" fx:id="btnMainOne" mnemonicParsing="false" prefHeight="51.0" prefWidth="398.0" text="Open second window" textFill="#4460ff">
<font>
<Font name="Times New Roman Bold" size="20.0" />
</font>
</Button>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
</children>
</AnchorPane>
</center>
</BorderPane>
MainController.java
import java.io.IOException;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MainController {
#FXML
private Button btnMainOne;
#FXML
private void initialize() {
btnMainOne.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
try {
Stage stage = new Stage();
stage.setTitle("Second stage");
stage.setScene(new Scene(root, 450, 450));
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
You can get the primary window by calling getScene().getWindow(). You can call hide() on it to hide it after you show the new stage, and you can register an event listener with the new stage that shows the primary window when the new stage is hidden:
#FXML
private void initialize() {
btnMainOne.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
Stage primaryStage = (Stage)btnMainOne.getScene().getWindow();
try {
Stage stage = new Stage();
stage.setTitle("Second stage");
stage.setScene(new Scene(root, 450, 450));
stage.setOnHidden(e -> primaryStage.show());
stage.show();
primaryStage.hide();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
Related
I am new to Java and JavaFX. I've created a JavaFX project using SceneBuilder/FXML and I'm attempting to add a realtime clock at the start of the program which works throughout the whole program at the top of the screen. I created a text area and tried to add the clock function from the code we were given but every time I start the program, it always shows up blank. Even doing trying to just use the .setText("string") function manually doesn't work so I think I'm putting the code in the wrong place. If possible, can someone tell me where this code should go or point me in the correct direction?
Here is my main:
package application;
import java.lang.ModuleLayer.Controller;
import java.util.Date;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
public class Main extends Application {
public static Stage stage = null;
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/Ui.fxml"));
Scene scene = new Scene(root);
stage.initStyle(StageStyle.UNDECORATED);
stage.setScene(scene);
this.stage = stage;
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is my controller code:
package application;
import java.util.Date;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextArea;
public class UiController {
#FXML
private TextArea clockTextArea;
#FXML
private TextArea transactionLog;
#FXML
private TextField recipentField;
#FXML
private Button payButton;
#FXML
private Button requestButton;
#FXML
private TextField commentField;
private void refreshClock()
{
Thread refreshClock = new Thread()
{
public void run()
{
while (true)
{
Date dte = new Date();
String topMenuStr = " " + dte.toString();
clockTextArea.setText(topMenuStr);
try
{
sleep(3000L);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} // end while ( true )
} // end run thread
};
refreshClock.start();
}
public void initialize() {
TextArea clockTextArea = new TextArea();
refreshClock();
}
}
It should be noted that whether it is in Swing or JavaFX, when updating the control, it needs to be done in the event dispatching thread, EDT, otherwise it will not work or throw Exception Not on FX application thread; currentThread = *
At this time, you only need to place the code of the update control code in the event dispatch thread for completion. Use the following code in JavaFX
Platform.runLater(new Runnable() {
#Override
public void run() {
//Update the control code of JavaFX and put it here
}
});
So change your code:
Date dte = new Date();
String topMenuStr = " " + dte.toString();
Platform.runLater(() -> clockTextArea.setText(topMenuStr));
and check if it works.
One route is to use Timeline to handle the clock. It's will be independent of your other code.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
/**
* JavaFX App
*/
public class App extends Application {
#Override
public void start(Stage stage) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("primary.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1080, 720);
stage.setScene(scene);
stage.show();
} catch (IOException ex) {
System.out.println(ex.toString());
}
}
public static void main(String[] args) {
launch();
}
}
PrimaryController
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.util.Duration;
public class PrimaryController {
#FXML Label lblClock;
Timeline clockHandler;
#FXML
void initialize()
{
Locale locale_en_US = Locale.US ;
DateTimeFormatter formatterUS = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ).withLocale( locale_en_US ) ;
clockHandler = new Timeline(
new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
LocalTime currentTime = LocalTime.now();
String outputUs = currentTime.format(formatterUS);
lblClock.setText(outputUs);
}));
clockHandler.setCycleCount(Timeline.INDEFINITE);
clockHandler.play();
}
}
Primary FXML
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="TOP_CENTER" prefHeight="720.0" prefWidth="1080.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.home.javafxrealtimeclock.PrimaryController">
<children>
<MenuBar>
<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>
<HBox>
<children>
<Label maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS" />
<Label fx:id="lblClock" text="00:00">
<HBox.margin>
<Insets />
</HBox.margin>
</Label>
</children>
<VBox.margin>
<Insets left="5.0" right="5.0" />
</VBox.margin>
</HBox>
<AnchorPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<Label layoutX="451.0" layoutY="331.0" text="The other parts of the program here" />
</children>
</AnchorPane>
</children>
</VBox>
I've started a project requested by our instructor building an application in JavaFX.
I used SceneBuilder for FXML Part when I want to add buttons on gridpane, but it didn't work. The connection with the database is okay. On the first part of the application, the user logs in. After that he/she comes on UserWindow, but the buttons aren't displayed.
File Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
Stage window;
Controller c;
ControllerB cB;
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
FXMLLoader f = new FXMLLoader();
FXMLLoader f2 = new FXMLLoader();
f.setLocation(Main.class.getResource("sample.fxml"));
f2.setLocation(Main.class.getResource("UserWindow.fxml"));
Parent root = f.load();
Parent root2 = f2.load();
Scene s = new Scene(root, 500, 340);
// Controllers
c = f.getController();
c.setMain(this);
c.setScene2(new Scene(root2, 900, 500));
cB = f2.getController();
cB.setMain(this);
cB.setScene(s);
window.setTitle("Remote Works");
window.setScene(s);
window.show();
}
public static void main(String[] args) {
launch(args);
}
public void setUserData(Object o) {
window.setUserData(o);
}
public void setScene(Scene scene) {
window.setScene(scene);
window.show();
}
public void setScene2(Scene scene) {
window.setScene(scene);
window.show();
}
}
File ControllerB.java:
package sample;
import javafx.collections.*;
import javafx.event.ActionEvent;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.*;
public class ControllerB implements Initializable {
#FXML
private GridPane Box;
#FXML
private Label nameUser;
#FXML
private Label matriculeUser;
#FXML
private Label fonctionUser;
#FXML
private Button deconnect;
private Scene scene1;
private Main main;
ObservableList<String> ecoles;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
try {
schoolretrieve();
int size = ecoles.size();
Node[] n = new Node[size];
for (int i = 0; i < n.length; i++) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Bloc.fxml"));
ControllerItem controller = new ControllerItem();
loader.setController(controller);
n[i] = loader.load();
controller.setButtonInst(ecoles.get(i)); // Until this part all works
Box.getChildren().add(n[i]); // But it doesn't add buttons to GridPane
}
} catch (IOException | NullPointerException | SQLException e) {
//System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
File ControllerItem.java:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class ControllerItem {
#FXML
private Button buttonInst;
public Button getButtonInst() {
return buttonInst;
}
public void setButtonInst(String s) {
buttonInst.setText(s);
}
}
File Bloc.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<Button fx:id="buttonInst" mnemonicParsing="false" prefHeight="132.0" prefWidth="201.0" stylesheets="#../styles.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" />
File UserWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="497.0" prefWidth="710.0" styleClass="pane" stylesheets="#../styles.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ControllerB">
<left>
<Pane prefHeight="497.0" prefWidth="156.0" BorderPane.alignment="CENTER">
<children>
<ImageView fitHeight="150.0" fitWidth="151.0" layoutX="11.0" pickOnBounds="true" preserveRatio="true" />
<Circle fill="#e1ebf5" layoutX="78.0" layoutY="88.0" opacity="0.18" radius="74.0" stroke="BLACK" strokeType="INSIDE" />
<Label fx:id="nameUser" layoutX="10.0" layoutY="196.0" prefHeight="50.0" prefWidth="136.0" text="Nom Utilisateur :" />
<Label fx:id="fonctionUser" layoutX="11.0" layoutY="259.0" prefHeight="37.0" prefWidth="136.0" text="Statut : " />
<Label fx:id="matriculeUser" layoutX="10.0" layoutY="306.0" prefHeight="37.0" prefWidth="136.0" text="Identifiant : " />
<Button fx:id="deconnect" layoutX="20.0" layoutY="364.0" mnemonicParsing="false" onAction="#onAction" prefHeight="27.0" prefWidth="117.0" text="deconnexion" />
</children>
</Pane>
</left>
<center>
<Pane opacity="0.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: #f7cc3d;"
BorderPane.alignment="CENTER">
<GridPane fx:id="Box" alignment="TOP_CENTER" hgap="3.0" layoutX="70.0" layoutY="96.0"
nodeOrientation="LEFT_TO_RIGHT" opacity="0.95" prefHeight="305.0" prefWidth="415.0"
styleClass="gridpane" stylesheets="#../ss.css" vgap="3.0"/>
</Pane>
</center>
</BorderPane>
So you have file UserWindow.fxml and you have declared a GridPane in it. I suggest you to don't make a separate .fxml file for the button.
Just do it like this in your ControllerB:
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
schoolretrieve();
int size = ecoles.size();
//Node[] n = new Node[size];
for (int i = 0; i < size; i++) {
//FXMLLoader loader = new FXMLLoader(getClass().getResource("Bloc.fxml"));
//ControllerItem controller = new ControllerItem();
//loader.setController(controller);
//n[i] = loader.load();
//controller.setButtonInst(ecoles.get(i));
//Box.getChildren().add(n[i]);
Button btn = new Button(ecoles.get(i));
Box.add(btn, 0, i); // Button is added to next row every time.
}
}
Hi I'm very new to Java and Javafx so I hope you can help me with a problem. I'm trying to do a proper MVC Pattern with Scene Builder but my code doesn't work and I don't know why.
I have understood that the Model class have to get the data and the Controller class should use and handle the data but I have big problems with that the Scene builder does accept one controller class for one FXML file. That is why I tried it with getters and setters to have the connection between Model and Controller.
But also I think I am not doing it right.
Main class:
package application;
import javafx.application.Application;
import javafx.fxml.*;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application{
#Override
public void start(Stage primaryStage) throws Exception{
try {
Parent root = FXMLLoader.load(getClass().getResource("/login/LoginUI.fxml"));
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startApp(Stage Stage) throws Exception{
try {
Parent root = FXMLLoader.load(getClass().getResource("/financeApp/UI.fxml"));
Scene scene = new Scene(root, 1022, 593);
Stage.setScene(scene);
Stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Controller class:
package login;
import application.Main;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import login.ModelLogin;
public class ControllerLogin {
#FXML TextField userNameField;
#FXML PasswordField passwordField;
#FXML Button loginButton;
ModelLogin model = new ModelLogin();
public void setUserName() {
model.setUserNameField(userNameField);
}
public void setPassword() {
model.setPasswordField(passwordField);
}
public void login(ActionEvent event) {
if (model.getUserNameField().getText().equals("test") && model.getPasswordField().getText().equals("1234")) {
Stage stage = new Stage();
Main startUI = new Main();
try {
startUI.startApp(stage);
} catch (Exception e) {
e.printStackTrace();
}
}else {
System.out.println("Try again");
}
}
}
Model class:
package login;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class ModelLogin {
private TextField userNameField;
private PasswordField passwordField;
public TextField getUserNameField() {
return userNameField;
}
public void setUserNameField(TextField userNameField) {
this.userNameField = userNameField;
}
public PasswordField getPasswordField() {
return passwordField;
}
public void setPasswordField(PasswordField passwordField) {
this.passwordField = passwordField;
}
}
and this is the FXML file created with Scene builder:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="290.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="login.ControllerLogin">
<children>
<AnchorPane prefHeight="290.0" prefWidth="400.0">
<children>
<Label alignment="CENTER" layoutX="150.0" layoutY="38.0" prefHeight="30.0" prefWidth="100.0" text="Login">
<font>
<Font name="System Bold" size="20.0" />
</font>
</Label>
<Label layoutX="159.0" layoutY="108.0" text="Benutzername">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Label>
<TextField fx:id="userNameField" layoutX="126.0" layoutY="125.0" onAction="#setUserName" />
<Label layoutX="175.0" layoutY="165.0" text="Passwort">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Label>
<PasswordField fx:id="passwordField" layoutX="126.0" layoutY="182.0" onAction="#setPassword" />
<Button fx:id="loginButton" layoutX="175.0" layoutY="233.0" mnemonicParsing="false" onAction="#login" text="Login" />
</children>
</AnchorPane>
</children>
</VBox>
Folders
I would be happy about some Feedback. Thank you!!
All UI elements should be in the view.
A model should have only information and logic that the view and controller use.
public class ModelLogin {
private final String userName;
private final String password;
ModelLogin(String userName, String password) {
this.userName = userName;
this.password = password;
}
boolean isCorrectCredentials(String userName, String password){
return this.userName.equals(userName)&&this.password.equals(password);
}
}
The controller "wires" the view and the model: it handles credential verification and
change of scene.
Note that it is modified to accept a reference of Main so it can change scene:
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class ControllerLogin {
#FXML TextField userNameField;
#FXML PasswordField passwordField;
private ModelLogin model;
private Main main;
#FXML
void initialize() {
model = new ModelLogin("test", "1234");
}
public void login(ActionEvent event) {
if (model.isCorrectCredentials(userNameField.getText(), passwordField.getText() )) {
try {
main.startApp();
} catch (Exception e) {
e.printStackTrace();
}
}else {
System.out.println("Try again");
}
}
void setMain(Main main) {
this.main = main;
}
}
The text field onAction is not used, so it was removed from the fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="290.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="login.ControllerLogin">
<children>
<AnchorPane prefHeight="290.0" prefWidth="400.0">
<children>
<Label alignment="CENTER" layoutX="150.0" layoutY="38.0" prefHeight="30.0" prefWidth="100.0" text="Login">
<font>
<Font name="System Bold" size="20.0" />
</font>
</Label>
<Label layoutX="159.0" layoutY="108.0" text="Benutzername">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Label>
<TextField fx:id="userNameField" layoutX="126.0" layoutY="125.0"/>
<Label layoutX="175.0" layoutY="165.0" text="Passwort">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Label>
<PasswordField fx:id="passwordField" layoutX="126.0" layoutY="182.0" />
<Button fx:id="loginButton" layoutX="175.0" layoutY="233.0" mnemonicParsing="false" onAction="#login" text="Login" />
</children>
</AnchorPane>
</children>
</VBox>
The Main was modified to get a reference to the controller, and to change scene:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application{
private Stage primaryStage;
private Parent root;
#Override
public void start(Stage primaryStage) throws Exception{
try {
this.primaryStage = primaryStage;
FXMLLoader loader = new FXMLLoader(getClass().getResource("/login/LoginUI.fxml"));
root = loader.load();
ControllerLogin controller = loader.getController();
controller.setMain(this);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startApp() throws Exception{
try {
root = FXMLLoader.load(getClass().getResource("/financeApp/UI.fxml"));
Scene scene = new Scene(root, 1022, 593);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
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>
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>
This is my first app and i have no idea why is my stage not clickable along with the menuBar. I use SceneBuilder for creating the fxml and I added the tree items in the controllers initialize method.
MainWindowController.java
package gui;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.MenuBar;
import javafx.scene.control.TreeItem;
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;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindowController extends AbstractController implements Initializable {
private Stage stage = null;
#FXML
private AnchorPane mainContainer;
#FXML
private VBox vBoxContainer;
#FXML
private MenuBar menuBarTop;
#FXML
private HBox hBoxContainer;
#FXML
private StackPane navigationSection;
#FXML
private TreeView<String> treeView;
final private TreeItem<String> rootIssues = new TreeItem<String>("IssueTracker");
final private TreeItem<String> issuesTable = new TreeItem<String>("IssuesTable");
final private TreeItem<String> stickers = new TreeItem<String>("Stickers");
#Override
public void initialize(URL location, ResourceBundle resources) {
rootIssues.setExpanded(true);
rootIssues.getChildren().addAll(issuesTable, stickers);
treeView.setRoot(rootIssues);
}
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.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="-Infinity" maxWidth="-Infinity" 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" />
</children>
</StackPane>
</children>
</HBox>
</children>
</AnchorPane>
The only thing different from my other stages is the TreeView. If i make it in the main class it works fine. I think that the problem is within the initialize method and the way I build the treeView, but I have no idea what it can be.
After trying what Gash suggested and running my MainWindow.fxml from Main, the MainWindowController and MainWindow.fxml worked fine. Now the only other thing that stands between the working example and my version is the way i start the stage and I'm doing that after successful login in the starting stage of the app.
HomeScreenController
package gui;
import connectivity.DataBaseHandler;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class HomeScreenController extends AbstractController implements Initializable {
private DataBaseHandler dbHandler = new DataBaseHandler();
#FXML
private AnchorPane homeWindow;
#FXML
private TextField insertNameField;
#FXML
private PasswordField insertPasswordField;
#FXML
private TextField insertDepartmentField;
#FXML
private Button signInButton;
#FXML
private Button signupButton;
private Main main;
#FXML
private Label mainAlertText;
private Stage stage = null;
#Override
public void initialize(URL url, ResourceBundle rb) {
signupButton.setOnAction((event)->{
showPopupWindow();
});
signInButton.disableProperty().bind(Bindings.createBooleanBinding( () -> (insertNameField.getText().isEmpty()
|| insertPasswordField.getText().isEmpty() || insertDepartmentField.getText().isEmpty()),
insertNameField.textProperty(), insertPasswordField.textProperty(), insertDepartmentField.textProperty()));
signInButton.setOnAction((event -> {
if (dbHandler.login(insertNameField.getText(), insertDepartmentField.getText(), insertPasswordField.getText())) {
mainAlertText.setTextFill(Color.GREEN);
mainAlertText.setText("Login Successfull");
closeStage();
showMainWidow();
} else {
mainAlertText.setTextFill(Color.RED);
mainAlertText.setText("One or more of the values are not correct");
}
}));
}
private void showPopupWindow() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("SignUpPopUp.fxml"));
// initializing the controller
SignUpPopUpController popupController = new SignUpPopUpController();
loader.setController(popupController);
Parent layout;
try {
layout = loader.load();
Scene scene = new Scene(layout);
// this is the popup stage
Stage popupStage = new Stage();
popupStage.setResizable(false);
// Giving the popup controller access to the popup stage (to allow the controller to close the stage)
popupController.setStage(popupStage);
if(this.main != null) {
popupStage.initOwner(main.getPrimaryStage());
}
popupStage.initModality(Modality.APPLICATION_MODAL);
popupStage.setScene(scene);
popupStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
public void showMainWidow() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainWindow.fxml"));
//initializing the controller
MainWindowController mainWindowController = new MainWindowController();
Parent layout;
try {
layout = loader.load();
Scene scene = new Scene(layout);
//the main stage
Stage mainStage = new Stage();
mainWindowController.setStage(mainStage);
if (this.main != null) {
mainStage.initOwner(main.getPrimaryStage());
}
mainStage.initModality(Modality.NONE);
mainStage.setScene(scene);
mainStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
public void showHomeScreen() {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("HomeScreen.fxml"));
loader.setController(this);
Parent layout;
try {
layout = loader.load();
Scene scene = new Scene(layout);
//this is the stage
Stage mainStage = new Stage();
this.setStage(mainStage);
mainStage.initModality(Modality.APPLICATION_MODAL);
mainStage.setScene(scene);
mainStage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setStage(Stage stage) {
this.stage = stage;
this.stage.setResizable(false);
this.stage.setTitle("SoloStats");
}
public Stage getStage() {
return this.stage;
}
public void closeStage() {
this.stage.close();
}
}
I should have provided this class earlier. Sorry for that.
It looks like your missing an import for your AbstractController, which should throw a compile error. I pasted your code into NetBeans and changed
public class MainWindowController extends AbstractController implements Initializable {
to
public class MainWindowController implements Initializable
Everything works as it should.
If you need the AbstractController, you will need to add the import. For example:
import org.springframework.web.servlet.mvc.AbstractController;
My working code looks nearly identical to yours. I'm not able to see any difference, but below are the copies of your code working for me.
MainWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?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="-Infinity" maxWidth="-Infinity" 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" />
</children>
</StackPane>
</children>
</HBox>
</children>
</AnchorPane>
MainWindowController:
package gui;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.MenuBar;
import javafx.scene.control.TreeItem;
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;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindowController implements Initializable {
private Stage stage = null;
#FXML
private AnchorPane mainContainer;
#FXML
private VBox vBoxContainer;
#FXML
private MenuBar menuBarTop;
#FXML
private HBox hBoxContainer;
#FXML
private StackPane navigationSection;
#FXML
private TreeView<String> treeView;
final private TreeItem<String> rootIssues = new TreeItem<String>("IssueTracker");
final private TreeItem<String> issuesTable = new TreeItem<String>("IssuesTable");
final private TreeItem<String> stickers = new TreeItem<String>("Stickers");
#Override
public void initialize(URL location, ResourceBundle resources) {
rootIssues.setExpanded(true);
rootIssues.getChildren().addAll(issuesTable, stickers);
treeView.setRoot(rootIssues);
}
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();
}
}
}
Gui.java: Added stage.setTitle here for window title to work.
package gui;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Gui extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
stage.setTitle("SoloStats - Welcome");
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I got a null pointer exception with your closeStage() call. Instead of using this.stage, try setting the stage using the signInButton and then close it. I'm guessing your login window is APPLICATION_MODAL and isn't closing properly which would prevent input events to your new window. You might find the Stage Docs very helpful.
Here's a snip for your closeStage:
public void closeStage() {
Stage stage = (Stage) signInButton.getScene().getWindow();
stage.close();
}