How to get to know which fxml file called the controller class while multiple fxml files have same controller class?
I have an initialize class in which I would like to auto complete two text fields from data in the database. As the controller class is same it throws an error when I run the program. So getting details about which fxml page called the controller class would help.
You shouldn't use the same controller class for different FXML files because then you won't need to deal with problems like this in the first place. However, if you insist you can manually call FXMLLoader.setController before loading the FXML (you also need to remove the reference to the controller inside the FXML), this way you know which controller instance is assigned to which FXML
Assuming you specify the fxml to load by passing a URL, not an InputStream, you simply need to add a URL location field that FXMLLoader can inject a value to. FXMLLoader automatically injects the fxml url to this field:
#FXML
private URL location;
#FXML
private void initialize() {
System.out.println(location);
}
Using the same controller for multiple fxmls with different functionality seems to be bad practice though. Please double check, if using different controllers wouldn't be a cleaner solution.
Note: Every time you load a fxml containing a fx:controller attribute with a controller class name as value, a new instance of the controller is created.
Related
Ever since I manually set my Controllers the corresponding views don't seem to recognise my controllers. None of the view elements are recognised by my controllers and none of my Controller methods are recognised by their views. When I hover over the onaction='#...eventHandler' in my views it says there is no controller specified for the top level element.
However, I have set my Controllers (this is the main Controller and then there is another controller set somewhere else for a pop up window):
FXMLLoader loader = new FXMLLoader(getClass().getResource("foodDiaryView.fxml"));
FoodDiary foodDiary = new FoodDiary();
FoodDiaryController controller = new FoodDiaryController(foodDiary);
loader.setController(controller);
Parent root = loader.load();
primaryStage.setTitle("Food Diary");
primaryStage.setScene(new Scene(root, 720, 480));
primaryStage.show();
When I run the program I get this error:
Exception in Application start method
java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.NullPointerException at sample.FoodDiaryController.initialize(FoodDiaryController.java:72)
Which is coincidentally the first line of code that references an element in the view:
#FXML private TableView<Food> breakfastTable;
And then in initialise (line 72) which caused the NullPointerException:
breakfastTable.setItems(foodDiary.getBreakfastFoods());
Anyone who could possibly allude to why this is happening?
Prerequisites:
I have to manually set my Controllers since I'm not using a no-arg constructor with my Controllers.
I'm using IntelliJ
I might be wrong and I can't check right now, but I remember some issues when using setController and setControllerFactory. I think when you've specified a fx:controller in your FXML then you can't use setController but must use the setControllerFactory or something like that.
I'm recently writing a javafx application and in one of its parts the client must wait for the server to get a list of people and after getting the list it must be used in a listview that is going to be added to a parent. That parent is and fxml file and after loading it I want to know if it is possible to add the vbox containing the listview to the parent or not. I'd be grateful if anyone could help...
From your question I gather you are not familiar with the idea of a controller or the associated FXML injection performed by a FXMLLoader. This answer by James_D goes over the very basics of the JavaFX lifecycle but it first goes over the basics of the procedure involved when loading a FXML file. If you want to modify the scene-graph that is loaded via FXML then you need to use a controller class with the appropriate FXML annotated fields. For example, let's say your parent is a BorderPane. In your FXML file you'd have:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:id="parent" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.1"
fx:controller="some.package.YourController">
<top>
<!-- maybe have something like a MenuBar here -->
</top>
<bottom>
<!-- maybe have a some type of status bar here -->
</bottom>
</BorderPane>
Notice the fx:controller attribute; it is the class name of the class to instantiate and use as a controller. Also note the fx:id attribute. In your controller class you'd have:
package some.package;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXML;
public class YourController {
#FXML
private BorderPane parent; // field name matches the fx:id attribute
#FXML
private void initialize() {
// do any initializing if needed (if not, get rid of this method)
// you can access and modify any FXML injected field from this method
}
}
Then you can use the parent via the controller instance. You could also create and link event handler methods in the controller and do certain behavior based on user actions. It's important to note, however, that how you change the state of the UI in the controllers depends on how you access you model classes. You'll need to have the model available to your controller and possibly have it shared between mutliple controllers. There are a decent number of questions/answers on Stack Overflow about how to do this already.
Here is another resource that may help you: Introduction to FXML.
Trying to acquaint myself with JavaFX I ran into the following problem:
I used Scene Builder to generate an FXML with my controller class specified as fx:controller="application.MainController" and I used the sample code generated by Scene Builder to create the MainController class in the according package.
Now although I'm not seeing any error messages apparently the initialize() method is never called after loading the FXML (tried Breakpoints and System.out.println). What am I missing?
I have a label and a button and when I press the button the label changes.
Now in order to continue i need to be able to access the label from another class. I tried to change the definition to public static in the aspx.designer.cs file but when I do that the button that changed the label before stopped working - i get a null exception. I tried to init the label but i can't find the right place to do it. Making a static method in the class, that will change the label's text didn't work as well because i can't change a non static variable in a static method.
How can I access a label from another class without getting a null exception or effecting the button that worked?
From a UserControl or a WebControl, you can access the Page with this.Page:
//From the Control File:
this.Page.TheLabel.Text = "blah";
Just make sure the label is public or you have a getter, and that you're not in a HttpContext (Not in a static method).
FIY, making the label static in the page would means there would only be one instance on the label shared by all the instance of pages. I doubt thats what you wants.
Better you can add a public property to the web control. Assign the label value to the public property and use it in any other place. It is better not to directly access label value from other files
I have created a root FXML which is a BorderPane and it has his own root controller.
I want to dynamicly add FXML's to the center of this borderpane.
Each of these fxml's share the same controller, root controller. I have done this in netbeans by choosing an exsisting controller when creating an empty FXML file.
I also have gave the nodes different id names, but the root controller does not recognize the nodes in these fxml's.
Is it possible to share the same controller for different fxml's?
Thanks in advance
Background
I don't know that sharing a controller instance is really recommended, at least I've never seen it done before.
Even if you set the controller class in each of the fxml's you are loading to the same value, it isn't going to share the same controller instance, because every time you load a controller, it will create a new instance (object) of the controller class (which doesn't seem to be what you want).
Potential Solutions
I haven't tried either of these solutions, but believe they will work.
The initialize method will probably be called each time you load a new fxml file. So you will want to account for that in your logic by making initialize idempotent.
A. Manually set the controller instance.
Remove all of the references to your controller class from your fxml files.
Manually create an instance of your controller class.
MyController controller = new MyController();
Set the controller to your controller instance before you load each fxml.
FXMLLoader loader = new FXMLLoader();
loader.setController(controller);
Panel panel = (Panel) loader.load("myfxml.fxml");
Repeat step 3 for each of your fxml files, using the same controller reference each time.
B. Use a controller factory.
You can set a controller factory on your fxml loaders and have the controller factory always return the same controller instance.