JavaFx form load - javafx

I want to group some radiobuttons in a togglegroup. The group is created in the controllerclass:
final ToggleGroup rbtGroup = new ToggleGroup();
Now i create a function which adds those buttons to the group. But how do i fire the function on the so called form-load?
I was writing Visual Basic for my company in the past few months, and there is an event called load on the form. Therefore, i can handle each event (load, change etc.) by simply writing my code in the prevailing event.
How do i achieve that on Java FX?
Excuse me for this question, but i find that the Java FX documentation is very confusing.

Your controller class has to implement the javafx.fxml.Initializable interface, and override (implement) the only method initialize(). This initialize() method (there is no function in Java terminology) is a "form load function" of the loading FXML file. So you can define and initiate controls and variables in this method like:
...
#FXML
private ToggleGroup rbtGroup;
#Override
public void initialize(URL url, ResourceBundle rb) {
rbtGroup = new ToggleGroup();
ToggleButton tb1 = new ToggleButton("ToggleButton 1");
tb1.setToggleGroup(rbtGroup);
ToggleButton tb2 = new ToggleButton("ToggleButton 2");
tb2.setToggleGroup(rbtGroup);
}
...
Note the #FXML annotation. Put it if the rbtGroup is defined in the loading FXML file.
Or call your "adding buttons to the group" method (again not function) in that initialize() method.

Related

javafx - how to get reference to main Stage in MainController in initialize() method?

I need to get reference to main Stage of app in initialize() method in MainController. I tried using this solution:
...
#FXML private Label label;
...
// in some method block
Stage stageTheLabelBelongs = (Stage) label.getScene().getWindow();
but other label (or other controlls) doesn't exist when application call initialize() and it returns NullPointerException. How to avoid this?
Greetings

JavaFX, Label null pointer exception

I am having the following problem with a program that I am currently writing, and I have searched on the internet, but I couldn't really find anything to help me understand the following problem
So inside another class I have written a method that executes this whenever the search button is clicked and the method looks like this:
public void searchButton(){
try {
new SearchController().display();
} catch (IOException e) {
e.printStackTrace();
}
}
And then the SearchController class looks something like this (I simplified it here):
public class SearchController {
#FXML
private Button cancelButton;
#FXML
private Label what;
private static Stage stage;
private static BorderPane borderPane;
#FXML
public void initialize(){
what.setText("Testing"); // this woks
cancelButton.setOnAction(e -> stage.close());
}
public void display() throws IOException {
stage = new Stage();
stage.setResizable(false);
stage.setTitle("Product search");
stage.initModality(Modality.APPLICATION_MODAL);
FXMLLoader loader = new FXMLLoader();
loader.setLocation(SearchController.class.getResource("Search.fxml"));
borderPane = loader.load();
Scene scene = new Scene(borderPane);
stage.setScene(scene);
//what.setText("Testing") and this doesn't work
stage.showAndWait();
}
}
Can someone please tell me why it is possible to write text on the initialize method (that method gets called after the borderPane = loader.load(); line...so why doesn't it work if I try to write on the label after that line?)
Thank you in advance
The FXMLLoader creates an instance of the class specified in the fx:controller attribute of the FXML root element. It then injects the elements defined in the FXML file into the controller instance it created when the fx:id attributes match the field names. Then it calls the initialize() method on that instance.
You create an instance of the controller "by hand" with new SearchController(). This is not the same object that is created by the FXMLLoader. So now when you have loaded the fxml file you have two different instances of SearchController. So if you call what.setText(...) from the display() method, you are not calling it on the controller instance created by the FXMLLoader. Consequently, what has not been initialized in the instance on which you are calling what.setText(...), and you get a null pointer exception.
Since initialize() is invoked by the FXMLLoader on the instance it created, when you call what.setText(...) from the initialize() method, you are calling it on the instance created by the FXMLLoader, and so the FXML-injected fields for that instance have been initialized.

How to initialize dialog window in nested controller

I'm developing a GUI application using Java8 and JavaFX. The main window has a button that should open new window (with it's own fxml). So far I've been loading the fxml each time the button was pressed but since the new window has tons of controls it (surprisingly) takes some time (aprox 0.5-1s) to open the popup, and thus I've changed the code so that the main controller loads the popup fxml in it's initialize method and whenever the button is clicked the pre loaded window is just shown.
It all works good but now I can't set the initOwner(...) on the new window since I don't have access to the window object in the initilize method. I know I don't have to set the initOwner, but then I have two application windows on the start menu (which I want to avoid). Any ideas how to go around this issue?
Also, what is the standard way of showing new windows/dialogs in JavaFX, should i load an fxml each time an event occurs or just show/hide the preloaded one?
You could load the FXML once in the initialize() method, then lazily initialize the dialog window when you need it. I.e.
public class Controller {
private Parent dialogPane ;
private Stage dialog ;
#FXML
private Button button ;
public void initialize() throws IOException {
dialogPane = FXMLLoader.load(getClass().getResource("dialog.fxml"));
}
#FXML
private void handleButtonPress() {
getDialog().show();
}
private Stage getDialog() {
if (dialog == null) {
Scene scene = new Scene(dialogPane);
dialog = new Stage();
dialog.setScene(scene);
dialog.initOwner(button.getScene().getWindow());
}
return dialog ;
}
}
You can lazy load the fxml. Namely not when app starts or not on every button click, but when it is requested:
private Parent popupPane;
private PopupPaneController popupPaneController;
private void openPopup( ActionEvent event ) {
if (popupPane == null) {
popupPane = FXMLLoader.load(...);
popupPaneController = // get it from FXMLLoader. Search this site for how
}
popupPaneController.updatePopupContent(newVals);
Stage popup = new Stage();
popup.initOwner(primaryStage);
stage.setScene(new ScrollPane(popupPane));
stage.show();
}
Note that if you cache the content of popup window, you can set initOwner() later. Also checkout the Alert class as an alternative for popup. See examples of it.
While showing the preloaded scene/window you may need to update the data shown in the popup. for this implement an updatePopupContent(newVals) method in popup controller's class, and call it on every button click as in code above.

(On javaFx) Is it Possible set Controls Fx:id One element of that Control Array in Scene Builder?

as all ready asked is it Possible?
For Example class controller have
#FXML
ImageView ImageViewArrays[];
set fx:id of one ImageView in Scene Builder ImageViewArrays[1] ?
I think On this Way: in controller class:
private ImageView s1;
#FXML
private ImageView s2;
#FXML
private ImageView s3;
#FXML
private ImageView s4;
#FXML
private ImageView s5;
On Scene Builder set fx:id of each ImageView ,s1...s5 and then and intergrade as array
ImageView Pic[]=new ImageView{s1,s2,s3,s4};
I'm not aware of any direct support in SceneBuilder 1.1 for arrays of controls.
However if you are dealing with a static array of controls on a form, then as Riporter mentioned it is trivial to generate the array of controls during the FXML load operation by including the statement he presented in the Initialize() method of your controller class.
Imageview[] m_pics = new Imageview[] {s1, s2, s3, s4, ...};
If you are needing to work with a dynamically generated array of controls, you can still use FXML to generate the base instance from which you can create an ArrayList in the controller class's Initialize() method, eg.:
private List<ImageView> m_pics;
#FXML
private ImageView iv1;
And then in your Initialize() method:
private void Initialize() {
m_pics = new ArrayList<>();
m_pics.add(iv1);
:
:
}
In this way, even though you must mix code with FXML in order to get what you want, by the time your controller class object is fully loaded, it still looks to you (or another programmer) like you created an array list of ImageView controls in FXML.

Stuck with event handling Java FX - Controller - Scene builder

I want to use Netbeans Java FX with Scene builder for a measurement application. I have designed a scene with controls. I can handle the events from the UI-controls within the '...Controller.java'.
The 'controller' is the standard piece of code that is referenced in the XML file and gets initialized by the system with:
public void initialize(URL url, ResourceBundle rb) { ..
My problem: how do I access my central, persisting, 'model' objects from within the controller? Or, to be more exact, from the event handlers created within the controller initialize function.
The 'model' object would be created within the application object.
The solution must be trivial, but I have not found a way to
either access the Application from the controller
or access the controller from within the Application.
What am I missing?
(the next question would be how to access the tree of panes within the object hierarchy created by screen builder, e.g. for graphics manipulation on output. Since the objects are not created by own code I can not store references to some of them. Ok, they could perhaps be found and referenced by tree-walking, but there must be a better way!)
Thanks for all insights!
I have used the 2nd approach (access the controller from within the Application) for awhile ago similar to following. In Application class:
//..
private FooController fooController;
private Pane fooPage;
private Model myModel;
#Override
public void start(Stage stage) {
//..
myModel = new Model();
getFooController().updateModel(myModel);
//..
Button button = new Button("Update model with new one");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Model myNewModel = new Model();
getFooController().updateModel(myNewModel);
}
}
// create scene, add fooPage to it and show.
}
private FooController getFooController() {
if (fooController == null) {
FXMLLoader fxmlLoader = new FXMLLoader();
fooPage = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
fooController = (FooController) fxmlLoader.getController();
}
return fooController;
}
Actually the first and second parts of your question is answered JavaFX 2.0 + FXML. Updating scene values from a different Task to the similar question of yours.

Resources