javafx communication between controller and main - java

Why does the following code always show null in the console when I want to get the controller ?
RenewCardFXML2_controller controller=loader.getController();
and the console prints null when i press the button.
I have two controllers and want to use textfield from the main app(membershipcards)-txt_numberOfCard_GENERAL inside the second fxml file whick has its own controller.
txt_numberOfCard_GENERAL.getText command from seccond controller and use its value.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package membershipcards;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.SplitPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import membershipcards.RenewCardFXML2_controller;
/**
*
* #author Primary
*/
public class mainGUIController implements Initializable {
#FXML
private ImageView logoimg;
#FXML
private SplitPane splitMenuContent;
#FXML
private Button btnCards;
#FXML
private Button btnRenewCard;
#FXML
private Button bntNewClient;
#FXML
private Button btnEditCard;
#FXML
private Button btnStatistics;
#FXML
private AnchorPane detailsPane;
#FXML
private Button btnCardN;
#FXML
public TextField txt_numberOfCard_GENERAL;
#FXML
public TextField txt_memberName_GENERAL;
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void loadCardsFXML1(ActionEvent event) {
try {
detailsPane = (AnchorPane) FXMLLoader.load(getClass().getResource("CardsFXML1.fxml"));
} catch (IOException ex) {
Logger.getLogger(mainGUIController.class.getName()).log(Level.SEVERE, null, ex);
}
splitMenuContent.getItems().set(1, detailsPane);
}
#FXML
private void loadRenewCardFXML2(ActionEvent event)throws IOException {
FXMLLoader loader = new FXMLLoader();
detailsPane = (AnchorPane) loader.load(getClass().getResource("RenewCardFXML2.fxml"));
splitMenuContent.getItems().set(1, detailsPane);
RenewCardFXML2_controller controller=loader.getController();
controller.setMGC(this);
System.out.println(controller);
}
}

The FXMLLoader.load(URL) method you are calling is a static method. Consequently, you have not called load on the FXMLLoader instance you created, and since that instance hasn't loaded the FXML, it has not initialized its controller field.
(A good IDE will give you a warning on your loader.load(...) line about calling a static method from a non-static context, or something similar. Eclipse, for example, says "The static method load(URL) should be accessed in a static way.")
The following will work:
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("RenewCardFXML2.fxml"));
detailsPane = loader.load();
splitMenuContent.getItems().set(1, detailsPane);
RenewCardFXML2_controller controller=loader.getController();
Note that you can reduce the first two lines of that code block to a single line
FXMLLoader loader = new FXMLLoader(getClass().getResource("RenewCardFXML2.fxml"));
detailsPane = loader.load();

Related

Switch scenes from one package to another package javafx [duplicate]

This question already has an answer here:
How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?
(1 answer)
Closed 2 years ago.
I have two packages p1 and p2.
P1 contains the main class, controller class and one fxml file.
P2 contains the controller class and one fxml file.
I want to switch from p1 fxml to p2 fxml file.
here is the code I tried. this is in P1 package.
public void btncontinue(ActionEvent event)throws IOException {
String filepath = "file:///D:/Programs/InteliJProjects/C/src/p1/sample2.fxml";
Parent nextScene = FXMLLoader.load(getClass().getClassLoader().getResource(filepath));
Scene scene = new Scene(nextScene);
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
}
The error i am getting is Location is required.
Well I've checked this is the code from scene1 to scene2
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import java.io.IOException;
public class sample
{
#FXML
RadioButton male;
#FXML
AnchorPane rootPane;
public void add() throws IOException
{
AnchorPane pane = FXMLLoader.load(getClass().getResource("two.fxml"));
rootPane.getChildren().setAll(pane);
}
}
And this is how to return from scene2 to scene1
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import java.io.IOException;
public class Two
{
#FXML
Button back;
#FXML
AnchorPane secPane;
public void returnBack() throws IOException
{
AnchorPane pane = FXMLLoader.load(getClass().getResource("sample.fxml"));
secPane.getChildren().setAll(pane);
}
}
I've tried this and it is working fine hope it will help you

How to set the value of JFXcombobox without using index?

How to set the value of combobox from the elements present in that combobox in java/javafx. This is the code what i have done till now.
package LetMeTest;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXComboBox;
import java.net.URL;
import java.util.ArrayList;
import java.util.Observable;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
public class TryController implements Initializable {
#FXML
private JFXComboBox<?> cb;
#FXML
private JFXButton btnGet;
#FXML
private JFXButton btnSet;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb)
{
ObservableList oo=FXCollections.observableArrayList("b","a");
cb.setItems(oo);
}
#FXML
private void doGetItem(ActionEvent event)
{
System.out.println("Selected Item="+cb.getSelectionModel().getSelectedItem());
}
#FXML
private void doSetItem(ActionEvent event)
{
cb.setValue("b");
}
}
I am trying to do it using ObservableList. Tell me there is any other possibility to do it.

JavaFX Textfield data to TableView in different Stage

I'm trying to input user data from TextField in new window into TableView in the main window. But it is not populating table, and I'm not getting any Exception. On button clicked new window just closes. I'm creating very simple app just to figure out how to communicate properly between controllers.
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 {
static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
this.primaryStage= primaryStage;
this.primaryStage.setTitle("Hello World");
this.primaryStage.setScene(new Scene(root));
this.primaryStage.show();
}
public void closeStage(){
primaryStage.close();
}
public static void main(String[] args) {
launch(args);
}
}
Controller class for main window where are table and button for opening new Stage:
package sample;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
#FXML TableView<radnici> tabela;
#FXML TableColumn<radnici, String> kolona;
#FXML Button dodajRadnikaDugme;
#FXML Button closeDugme;
Main main = new Main();
static Stage stage = new Stage();
Scene scene;
BorderPane borderPane;
#Override
public void initialize(URL location, ResourceBundle resources) {
kolona.setCellValueFactory(new PropertyValueFactory<radnici, String>("ime"));
}
public TableView<radnici> getTabela() {
return tabela;
}
public TableColumn<radnici, String> getKolona() {
return kolona;
}
//Opening new Stage on button clicked
public void dodajRadnikaDugemKlik() throws IOException {
FXMLLoader loader = new FXMLLoader();
borderPane = new BorderPane();
loader.setLocation(getClass().getResource("dodajRadnika.fxml"));
borderPane = loader.load();
scene = new Scene(borderPane);
stage.setTitle("Dodaj Radnika");
stage.setScene(scene);
stage.showAndWait();
}
//Closing main window
public void closeDugmeKlik(){
main.closeStage();
}
//Method for closing new window
public void CloseStage(){
stage.close();
}
}
Controller class for the new Window where are just TextField and Button:
package sample;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import java.io.IOException;
public class dodajRadnikaKontroler {
#FXML TextField upišiRadnika;
#FXML Button dodajRadnika;
BorderPane borderPane;
public void initialize(){
System.out.println("učitavanje podataka...");
}
//Method for adding data on button clicked from TextField into table in main window
#FXML public void dodajRadnikaKlik() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("sample.fxml"));
borderPane = new BorderPane();
borderPane = loader.load();
Controller controller = loader.getController();
ObservableList<radnici> lista = FXCollections.observableArrayList();
lista.add(new radnici(upišiRadnika.getText()));
controller.tabela.setItems(lista);
upišiRadnika.clear();
controller.CloseStage();
}
}
Model Class for workers ("radnici"):
package sample;
public class radnici {
private String ime;
public radnici(String ime) {
this.ime = ime;
}
public String getIme() {
return ime;
}
public void setIme(String ime) {
this.ime = ime;
}
}
Please can someone help me so that I can finally do this properly.
Note: please use proper naming conventions. I have changed some names of classes so that they follow standard conventions.
You don't see the changes to your table, because you are loading a entire new UI structure from the FXML file, including a new TableView, and then you set the items in that new table view.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("sample.fxml"));
borderPane = new BorderPane();
// load a new UI from the FXML file:
borderPane = loader.load();
// get the controller for the new UI:
Controller controller = loader.getController();
ObservableList<radnici> lista = FXCollections.observableArrayList();
lista.add(new radnici(upišiRadnika.getText()));
// set the table items in the new UI:
controller.tabela.setItems(lista);
upišiRadnika.clear();
controller.CloseStage();
Since you don't even display this new UI, you don't see the items in the table.
Presumably what you actually want to do is update the items in the existing table. All you need for this is a reference to the table's backing list. You need to pass that to the controller for the second FXML file. Add a field and method to DodajRadnikaKontroler:
public class DodajRadnikaKontroler {
// Existing code omitted:
private ObservableList<Radnici> items ;
public void setItems(ObservableList<Radnici> items) {
this.itmes = items ;
}
}
and then pass the table's list to the new controller when you load the FMXL file:
//Opening new Stage on button clicked
public void dodajRadnikaDugemKlik() throws IOException {
FXMLLoader loader = new FXMLLoader();
borderPane = new BorderPane();
loader.setLocation(getClass().getResource("dodajRadnika.fxml"));
borderPane = loader.load();
DodajRadnikaKontroler controller = loader.getController();
controller.setItems(tabela.getItems());
scene = new Scene(borderPane);
stage.setTitle("Dodaj Radnika");
stage.setScene(scene);
stage.showAndWait();
}
and now in the dodajRadnikaKlik() method you just update the list:
#FXML public void dodajRadnikaKlik() throws IOException {
// if you want to add an item:
items.add(new radnici(upišiRadnika.getText()));
// if you want to replace all items with the new one:
// items.setAll(new radnici(upišiRadnika.getText()));
upišiRadnika.clear();
controller.CloseStage();
}

JavaFX getting input from a textfield

I have just started learning java fx and I am trying to get user input from two text field. Once they click the button this will be displayed on a console.
However, I am keep getting an error and cannot figure out why.
I have assigned the 'handle' function using Scenebuilder, the error is pointing at the method.
Main Class:
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 {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller:
package sample;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
public class Controller {
public TextField userField;
public TextField passField;
public Button logButton;
public void handle(ActionEvent event) {
String username = userField.getText();
String passw = passField.getText();
System.out.printf("Logged in as %s %s", username, passw);
}
}
although you didn't show the error, but i think it's because you didn't annotate the fields userField and passwordField with #FXML annotation
by this annotation you tie the fields in the controller with fields in the fxml
so to solve this problem let's do the following simple steps
public class Controller implements Initializable{
#FXML
private TextField userField;
#FXML
private TextField passField;
#FXML
private Button logButton;
private void handle(ActionEvent event)
{
System.out.println(userField.getText());
}
#Override
public void initialize(URL url, ResourceBundle rb)
{
logButton.setOnAction(this::handle);
}}
and in the scene builder follow this image
try this,and if you still have problems just let a comment (:
As you are using Scene Builder, you should use the sample controller skeleton: Under View, select Use Sample Controller Skeleton. Also, specify the "On Action" for the text field. Scene Builder will dot the i's and cross the t's for you.

JavaFX, Open a Screen in same Window

I'm trying to implement an application, which has a simple navigation. One Main Menu, 3 Submenus, with another 3 Submenus each.
I need the application open every submenu recursively in the same Window with the Mainmenu as the root screen. I must be able to return to that menu by going via the "Back" Button on each Submenu.
I implemented a Main class, a Controller Class and a FXML-file for EACH (!) Menu and Submenu.
E.g. my Main Menu
package application;
import org.apache.log4j.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
public class Main extends Application {
// Initialize Logger
private static final Logger logger = Logger.getLogger(Main.class);
#Override
public void start(Stage primaryStage)
{
try
{
AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("MainFrame.fxml"));
Scene scene = new Scene(root,1000,500);
primaryStage.setScene(scene);
primaryStage.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
logger.info("Starting application.");
launch(args);
}
}
My MainController
package application;
import org.apache.log4j.Logger;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MainFrameController
{
private static final Logger logger = Logger.getLogger(MainFrameController.class);
#FXML
private Button btn_random1;
#FXML
private Button btn_random2;
#FXML
private Button btn_random3;
#FXML
private Button btn_random4;
public void initialize()
{
//mainService = new MainService();
}
#FXML
private void onRandomButton1() throws Exception
{
logger.info("onRandomButton1Clicked");
Stage stage = new Stage();
AnchorPane root;
root = (AnchorPane)FXMLLoader.load(getClass().getResource("RandomFXML1.fxml"));
Scene scene = new Scene(root,1000,500);
stage.setScene(scene);
stage.show();
}
#FXML
private void onRandomButton2()
{
logger.info("onRandomButton1");
}
#FXML
private void onRandomButton3()
{
logger.info("onRandomButton2");
}
#FXML
private void onRandomButton4()
{
Platform.exit();
logger.info("onRandomButton3");
}
}
Is there a way to simply change my code, so it does open in the same window?
I took a look at several tutorials with relatively complex ways of solving this, I'd like to stick to my code and not changing too much, otherwise I'd have to start all over again.
Pls note, that this is only one of many Main/Controller/FXML combinations, I have about 10 screens and "subscreens", which are being navigated like this (by java opening a new window).
Ideas anyone? Or maybe a relatively simple tutorial (for which I dont have to change my whole code)?
Thanks!
Have an empty controller at the root (or perhaps with a single empty anchorpane) and have it open the other controllers and add it to the current pane?
I currently have a similar setup but with a tab pane: each module is loaded into a separate tab. Each module itself has an fxml file, a controller etc. The core code dynamically creates new tabs etc for each module and loads them.

Categories