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.
}
}
Related
I have tried researching various pages regarding how to switch scenes or even stages with no luck to help my specific case. I am trying to create a program with a login form that manages a school library.
I have a login form that authenticates the user input with the method validateLogin(). If the login is successful (i.e. isLoginSuccess = true), I want my program to close primaryStage and open a new stage/window with the library management system.
Is it better to switch the scene on primaryStage or close primaryStage and open a new stage? How do you do that and should you do that from Main.java or is it fine to do it from LoginController.java? I'm having trouble switching scenes or even just creating a new stage from LoginController.java since primaryStage isn't recognized in that class.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application
{
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setScene(new Scene(root, 520, 400));
primaryStage.setResizable(false);
primaryStage.show();
}
//main() method is ignored in correctly deployed JavaFX application.
public static void main(String[] args)
{
launch(args);
}
}
LoginController.java
package sample;
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.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.stage.StageStyle;
import java.io.File;
import java.util.ResourceBundle;
//Can be removed, StackOverflow import
import java.io.BufferedReader;
import java.io.FileReader;
import java.net.URL;
public class LoginController implements Initializable
{
#FXML
private Button cancelButton;
#FXML
private Label loginMessageLabel;
#FXML
private ImageView brandingImageView;
#FXML
private ImageView lockImageView;
#FXML
private TextField usernameTextField;
#FXML
private PasswordField enterPasswordField;
#Override
public void initialize(URL url, ResourceBundle resourceBundle)
{
File brandingFile = new File("Images/LibManager.png");
Image brandingImage = new Image(brandingFile.toURI().toString());
brandingImageView.setImage(brandingImage);
File lockFile = new File("Images/LoginLock.png");
Image lockImage = new Image(lockFile.toURI().toString());
lockImageView.setImage(lockImage);
}
//Activates validateLogin() if there is input in text fields.
public void loginButtonOnAction(ActionEvent event)
{
if (usernameTextField.getText().isBlank() == false && enterPasswordField.getText().isBlank() == false)
{
validateLogin();
}
else
{
loginMessageLabel.setText("Please enter username and password");
}
}
//Closes login window.
public void cancelButtonOnAction(ActionEvent event)
{
Stage stage = (Stage) cancelButton.getScene().getWindow();
stage.close();
}
//Compares user input to txt file contents to authenticate.
public void validateLogin() {
{
try {
String location = "userdatabase.txt";
String username = usernameTextField.getText();
String password = enterPasswordField.getText();
FileReader fr = new FileReader(location);
BufferedReader br = new BufferedReader(fr);
String line, user, pass;
boolean isLoginSuccess = false;
while ((line = br.readLine()) != null) {
user = line.split(" ")[1].toLowerCase();
pass = line.split(" ")[2].toLowerCase();
if (user.equals(usernameTextField.getText()) && pass.equals(enterPasswordField.getText())) {
isLoginSuccess = true;
break;
}
}
if (!isLoginSuccess)
{
/*
public void startLibManager(Stage primaryStage) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("LibDatabase.fxml"));
Parent mainCallWindowFXML = loader.load();
secondaryStage.initStyle(StageStyle.UNDECORATED);
secondaryStage.setScene(new Scene(root, 520, 400));
secondaryStage.setResizable(false);
secondaryStage.show();
}
*/
/*
//use one of the components on your scene to get a reference to your scene object.
Stage stage = (Stage)tfCallerName.getScene.getWindow();//or use any other component in your controller
Scene mainCallWindow = new Scene (mainCallWindowFXML, 800, 600);
stage.setScene(newCallDetails);
stage.show(); //this line may be unnecessary since you are using the same stage.
*/
}
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
login.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="520.0" style="-fx-background-color: #FFFFFF;" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LoginController">
<left>
<AnchorPane prefHeight="407.0" prefWidth="227.0" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="brandingImageView" fitHeight="400.0" fitWidth="226.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../Images/LibManager.png" />
</image>
</ImageView>
</children></AnchorPane>
</left>
<right>
<AnchorPane prefHeight="400.0" prefWidth="332.0" style="-fx-background-color: FFFFFF;" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="lockImageView" fitHeight="32.0" fitWidth="46.0" layoutX="134.0" layoutY="65.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../Images/LoginLock.png" />
</image>
</ImageView>
<Label layoutX="23.0" layoutY="157.0" prefHeight="17.0" prefWidth="60.0" text="Username" textFill="#01989e" />
<TextField fx:id="usernameTextField" layoutX="96.0" layoutY="152.0" prefWidth="173.0" promptText="Username" />
<Label layoutX="26.0" layoutY="205.0" text="Password" textFill="#01989e" />
<PasswordField fx:id="enterPasswordField" layoutX="96.0" layoutY="200.0" prefHeight="27.0" prefWidth="173.0" promptText="Password" />
<Button fx:id="loginButton" layoutX="22.0" layoutY="294.0" mnemonicParsing="false" onAction="#loginButtonOnAction" prefHeight="27.0" prefWidth="249.0" style="-fx-background-color: ff914d;" text="Login" textFill="WHITE" />
<Button fx:id="cancelButton" layoutX="22.0" layoutY="342.0" mnemonicParsing="false" onAction="#cancelButtonOnAction" prefHeight="27.0" prefWidth="249.0" style="-fx-background-color: ff914d;" text="Cancel" textFill="WHITE" />
<Label fx:id="loginMessageLabel" layoutX="26.0" layoutY="248.0" prefHeight="17.0" prefWidth="160.0" textFill="RED" />
</children></AnchorPane>
</right>
</BorderPane>
#Loritt I might be a bit late, but I use this method to change scenes when using JavaFX.
If you are going to be changing back and forth between scene, this method keeps you from having to write redundant code.
Stage stage;
Parent scene;
public void switchViews(ActionEvent event, String fileLocation) throws IOException {
stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
scene = FXMLLoader.load(getClass().getResource(fileLocation));
stage.setScene(new Scene(scene));
stage.show();
}
I usually put this method inside the controller class which is completely acceptable as it has to do with the controlling of the visuals in the application and not any business logic.
Also, when I was originally learning how to do this myself and then pass information between the scenes I used this video and youtuber who has some good content on JavaFX/Scene Builder. (Link: https://www.youtube.com/watch?v=XCgcQTQCfJQ)
Hope this helps answer your question.
Happy coding! :)
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();
}
I want to load the TreeView defined in my FXML file into a TreeView variable in my java code.
But always when I try it the TreeView is NULL.
I looked everywhere, Google, so many questions and answers here but nothing worked out.
I need the TreeView to add dynamicly TreeItems to it.
Here my IconOverview.FXML file located in src/rn.IconTool.view:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import rn.IconTool.model.*?>
<?import javafx.scene.control.TreeView?>
<AnchorPane prefHeight="584.0" prefWidth="966.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="rn.IconTool.model.IconOverviewControllerClass">
<children>
<SplitPane dividerPositions="0.229253112033195" layoutX="2.0" layoutY="34.0" prefHeight="547.0" prefWidth="966.0">
<items>
<AnchorPane fx:id="splitPaneMenu" minHeight="0.0" minWidth="0.0" prefHeight="545.0" prefWidth="353.0">
<children>
<TreeView fx:id="treeview" layoutX="-5.0" onMouseClicked="#ShowContextMenu" prefHeight="545.0" prefWidth="218.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="533.0" prefWidth="675.0">
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="545.0" prefWidth="702.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fitHeight="95.0" fitWidth="104.0" layoutX="22.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
</children>
</AnchorPane>
</items>
</SplitPane>
<ToolBar layoutY="-1.0" prefHeight="30.0" prefWidth="968.0" />
</children>
</AnchorPane>
my RootLayout.fxml, located in .view too
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<?import rn.IconTool.model.*?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="rn.IconTool.model.NewCategoryClass">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
<MenuItem mnemonicParsing="false" onAction="#NewtCategory" text="New Category" />
</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>
</top>
</BorderPane>
the CreateNewCategoryScreen.fxml in .view too
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<?import rn.IconTool.model.*?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="rn.IconTool.model.NewCategoryClass">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
<MenuItem mnemonicParsing="false" onAction="#NewtCategory" text="New Category" />
</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>
</top>
</BorderPane>
And my ContextMenuPane.fxml although located in .view:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="254.0" prefWidth="166.0" xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/8">
<!-- TODO Add Nodes -->
</AnchorPane>
And here for the Controller Class where I try to get the TreeView src/rn.IconTool.model IconOverviewControllerClass:
package rn.IconTool.model;
import java.io.IOException;
import rn.IconTool.MainApp;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.TreeView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
public class IconOverviewControllerClass {
#FXML TreeView treeview;
#FXML private AnchorPane splitPaneMenu;
public IconOverviewControllerClass(){
}
#FXML
public void ShowContextMenu(MouseEvent r){
GetInTouchWithContextMenu git = new GetInTouchWithContextMenu();
// treeview = (TreeView<String>) getScene().lookup("#treeview");
if(r.getButton() == r.getButton().SECONDARY){
System.out.println("Rechtsklick");
ContextMenu contextM = git.getTheContextMenu();
System.out.println(contextM.toString());
// treeview.setContextMenu(contextM);
//
// contextM.show(treeview, r.getX(), r.getY());
// System.out.println(contextM.isShowing());
System.out.println("X: " + r.getX() + " Y: " + r.getY());
}
}
public TreeView<?> getTreeView() throws IOException{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/IconOverview.fxml"));
AnchorPane iconOverview = (AnchorPane) loader.load();
treeview = (TreeView<?>) iconOverview.lookup("#treeview");
System.out.println("TreeIconOver: " + treeview + " iconOverView: " + iconOverview);
return treeview;
}
}
And my class for creating a Contextmenu what isnĀ“t working but no so worse. src/rn.IconTool.model
GetInTouchWithContextMenu:
package rn.IconTool.model;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.stage.WindowEvent;
public class GetInTouchWithContextMenu {
private ContextMenu contextM = null;
public GetInTouchWithContextMenu(){
getContextMenu();
}
private void getContextMenu(){
contextM = new ContextMenu();
contextM.setOnShowing(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("showing");
}
});
contextM.setOnShown(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("shown");
}
});
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
contextM.getItems().addAll(item1);
}
public ContextMenu getTheContextMenu(){
return contextM;
}
}
And here is my screen to create new TreeItems for my TreeView src/rn.IconTool.model NewCategoryClass
package rn.IconTool.model;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import rn.IconTool.MainApp;
public class NewCategoryClass {
private AnchorPane categoryPane;
private Stage stage;
private Scene scene;
private Node rootIcon;
#FXML private javafx.scene.control.Button closeButton;
#FXML private javafx.scene.control.TextField categoryName;
#FXML private javafx.scene.control.TextField categoryIconName;
#FXML private javafx.scene.control.TreeView<String> treeview;
public NewCategoryClass(){
//System.out.println("Neue Kategorie erstellen.");
}
#FXML
private void NewtCategory() throws IOException{
System.out.println("Neue Kategorie angelegt.");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/CreateNewCategoryScreen.fxml"));
categoryPane = (AnchorPane) loader.load();
scene = new Scene(categoryPane);
closeButton = (Button) scene.lookup("#closeButton");
stage = new Stage();
stage.setTitle("Set New Category");
stage.setScene(scene);
stage.show();
}
#FXML
private void FinishButtonlistener() throws IOException{
// get a handle to the stage
Stage stage = (Stage) closeButton.getScene().getWindow();
// do what you have to do
System.out.println("Textfeld: " + categoryName.getText());
// leeres Textfeld = leerer String
TreeItem<String> rootItem;
if(categoryName.getText().equals("")){
}else{
if(categoryIconName.getText().equals("")){
rootItem = new TreeItem<String> (categoryName.getText());
}else{
setRootIcon(categoryIconName.getText());
rootItem = new TreeItem<String> (categoryName.getText(), getRootIcon());
}
IconOverviewControllerClass iocc = new IconOverviewControllerClass();
iocc.getTreeView();
// treeview.setRoot(rootItem);
//System.out.println("AnchorPane: " + splitPaneMenu);
System.out.println("Treeview: " + treeview);
System.out.println("TreeItem: " + rootItem);
stage.close();
}
}
private void setRootIcon(String iconName){
rootIcon = new ImageView( new Image(this.getClass().getResourceAsStream(iconName)));
}
public Node getRootIcon(){
return rootIcon;
}
public Stage getStage(){
return stage;
}
public Scene getScene(){
return scene;
}
}
My main located in src/rn.IconTool
package rn.IconTool;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private AnchorPane iconOverview;
private Scene scene;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Icon Place");
initRootLayout();
showIconOverview();
}
/**
* Initializes the root layout.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void showIconOverview() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/IconOverview.fxml"));
iconOverview = (AnchorPane) loader.load();
rootLayout.setCenter(iconOverview);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
* #return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
public Scene getScene(){
return scene;
}
}
I hope someone of you can help me
If you need the other classes to build the complete program then ask but I hope you have some ideas that the TreeView is not null ;)
You don't have to lookup the treeview with :
treeview = (TreeView) iconOverview.lookup("#treeview");
You automatically retrieve the treeView with the fx:id defined in the fxml file and the annotation #FXML in the controller.
I know why my TreeView was NULL. I forgot to implements javafx.fxml.Initializable and add the unimplemented method.
Here is my new IconOverviewControllerClass and dont worry about the static TreeView is only for test purpose ;)
package rn.IconTool.model;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.TreeView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
public class IconOverviewControllerClass implements javafx.fxml.Initializable{
#FXML public TreeView<String> treeview;
#FXML private AnchorPane splitPaneMenu;
private static TreeView<String> statictreeView;
public IconOverviewControllerClass(){
}
#FXML
public void initMyComponents(MouseEvent r) throws IOException{
if(getTreeView() == null){
System.out.println(treeview);
statictreeView = treeview;
System.out.println("static init: " + statictreeView);
}
ShowContextMenu(r);
}
public void ShowContextMenu(MouseEvent r){
if(r.getButton() == r.getButton().SECONDARY){
System.out.println("Rechtsklick");
GetInTouchWithContextMenu git = new GetInTouchWithContextMenu();
ContextMenu contextM = git.getTheContextMenu();
System.out.println(contextM.toString());
treeview.setContextMenu(contextM);
contextM.show(treeview, r.getX(), r.getY());
System.out.println(contextM.isShowing());
System.out.println("X: " + r.getX() + " Y: " + r.getY());
}
}
public TreeView<String> getTreeView() throws IOException{
return statictreeView;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
//System.out.println(treeview);
statictreeView = treeview;
}
}
I am trying to create a tree with custom check boxes. There is no option in the Scenebuilder with such an option. I tried to write the code in the controller, but did not work.
Someone please help me out.
FXML and the controller code:
the CheckBoxTreeItem is not working.
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="486.9609375" prefWidth="472.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="abcd.controller">
<!-- TODO Add Nodes -->
<children>
<Button id="button" fx:id="button1" layoutX="99.0" layoutY="51.0" mnemonicParsing="false" onAction="#processLogin" text="Button" />
<TextArea fx:id="textarea" layoutX="40.0" layoutY="83.0" prefHeight="76.0" prefWidth="129.0" wrapText="true" />
<TreeView fx:id="treeview" layoutX="69.0" layoutY="204.0" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.CheckBoxTreeItemBuilder;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.util.Callback;
public class controller implements Initializable {
// Binding with the FXML
#FXML
private Button taskBarButton1;
#FXML private TextArea textarea;
#FXML private TreeView<String> treeview;
#FXML private CheckBoxTreeItem<String> root;
//#FXML private CheckBoxTreeItem<String> rootitem ;
#FXML
private void processLogin(ActionEvent event) {
textarea.appendText("clicked");
}
public void loadonstart()
{
for (int i=0; i<5;i++)
{
//System.out.println("numbers" +i);
textarea.appendText("\n"+i);
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {
loadonstart();
loadtreeitems();
}
private void loadtreeitems()
{
CheckBoxTreeItem<String> root = new CheckBoxTreeItem<String>("Source Root");
root.setExpanded(true);
TreeView<String> tree = new TreeView<String> (root);
//tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
for (int j=10; j<15; j++)
{
root.setExpanded(true);
root.getChildren().add(new CheckBoxTreeItem<String>("" +j));
}
treeview.setRoot(root);
}
}