I have a main app class and a fxmlController class but I am entangled in connecting/organizing(confused how these are called and how I should organize them to make the GUI connected business logic) business logic and GUI. Can someone please tell the order in which following function are called or can anyone help how I should call them?
public void Main() //constructor
public static void main() // our main
public void start() //I don't know what it is, what purpose it has
// and where should be called
//Note: In main function there is a call as following
public void initialize() //I don't know what it is and what purpose it has
public fxmlController() // which function should be called here....
NOTE: I know about FXMLLoader();
please someone explain
I think of an FXML file and its corresponding controller as a pair that manage the user interface. In larger applications you might have several such FXML-controller pairs that make up different parts of the user interface. Within each pair, the FXML file defines the layout of the UI, and the controller defines the logic (i.e. it typically processes user input, etc).
While you said you "know about FXMLLoader
", if you understand that fully you would actually understand some of the other things you asked about, so:
The user interface defined by an FXML file and its controller is loaded into memory by an FXMLLoader
. In the simplest setup, the controller is defined by a fx:controller
attribute in the root element of the FXML file. When the load()
method is called on the FXMLLoader
, it:
fx:controller
attribute, by calling its no-argument constructor@FXML
-annotated fields in the controller to the elements defined with matching fx:id
attributesinitialize()
method on the controller, if there is one.Notice the order of those events: the constructor is called before the @FXML
-annotated fields are injected, but the initialize()
method is called after. This means you can access (and configure) and @FXML
-annotated fields in the initialize()
method, but not in the constructor. It is quite common (at least in simple applications) not to define any constructor in the controller classes and just to use the default.
You can have as many FXML/controller pairs in your application as you need/want. Each FXML file should have its own controller class. You can load an FXML file as many times as you need if you want multiple instances of the UI it defines: each time the FXMLLoader
will create a new controller instance for you that is associated with the UI element you loaded.
The Application
subclass (you called it Main
) represents the entire application. You should have only one such class per application and only one instance of it, which is created for you by the FX toolkit.
When you start a FX application (which I'll describe below), the FX toolkit is started. Then an instance of your Application
subclass is created, and its init()
method is called (if you don't define one, the default implementation does nothing). The FX Application Thread is then started and the Application
subclass instance's start()
method is called on that thread.
Your start()
method should do pretty minimal work. Typically it will load your "main" fxml file, place the resulting UI in a scene, put the scene in the stage, and show the stage. All the logic will be handled by the controller for the FXML file, not by the Application
subclass.
In more advanced applications, you might start some background services and/or create some data models in your init()
method, and connect them with the controller in the start()
method, but the ideas above are the basics.
The actual startup process can happen in a couple of ways. If you are using the standard Oracle JRE, then launching an Application
subclass with
java Main
(where Main extends Application
) will cause the process above to happen; in other words the FX toolkit is started, an instance of Main
is created, its init()
method is called, and it's start()
method is called on the FX Application Thread.
Other environments (particularly IDEs) are not aware of the JavaFX startup process, and expect the class you are executing to have a public static void main(String[] args)
method, like any standard Java application class. To support these environments, it is common for your Application
subclass to define a main(...)
method which simply calls launch(...)
(a static method inherited from Application
). The launch
method forces the FX toolkit to start, etc. It can only be called once during any application lifetime.
So now you have something like:
package com.example ;
// imports...
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// just load fxml file and display it in the stage:
FXMLLoader loader = new FXMLLoader(getClass().getResource("mainUI.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
// main method to support non-JavaFX-aware environments:
public static void main(String[] args) {
// starts the FX toolkit, instantiates this class,
// and calls start(...) on the FX Application thread:
launch(args);
}
}
Then you would have mainUI.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import java.util.ArrayList?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.MyController">
<Label fx:id="label1"/>
<Label fx:id="label2"/>
</VBox>
and the controller
package com.example ;
// imports...
public class MyController {
@FXML
private Label label1 ;
@FXML
private Label label2 ;
// called by the FXML loader after the labels declared above are injected:
public void initialize() {
// do initialization and configuration work...
// trivial example, could also be done directly in the fxml:
label1.setText("Foo");
label2.setText("Bar");
}
}