Reputation:
I've studied all popular GUI patterns - MVP,MVC,MVVM and finally I decided to implement MVP (Supervising Controller). So I have the following OBJECTS(!). Stage<-View<->Model
. It's important Stage!=View, it is another object. Between view and model data binding. Besides I have a presenter(controller) which handles all events and works with view and model, so View<-ViewInterface<-Controller->Model
.
The problem is now how to get references to labels, textAreas etc in view. Javafx allows to use @FXML annotation to inject these components to controller. However, using MVP I need these components in View, as all logic for view is in View and I don't need them in controller. The only solution I know is:
public class MyView{
private Button button;
public MyView(){
...
button=(Button) root.lookup("#myButton");
}
}
That is to get references by their ID. However I don't like it. Or I do something wrong or I understand something wrong but I think a better solution exist. Please, help me to find it.
Upvotes: 4
Views: 8930
Reputation: 36
I know this question is very old, but I still decided to write my answer here.
I will start by saying that despite being advertised as following MVC pattern, JavaFX/FXML really follows MVP pattern by default.
There are several good articles about MVC vs MVP (Baeldung - MVC vs MVP, GeeksForGeeks - MVC, MVP, MVVM). Here I will point key main differences.
MVC pattern
org.springframework.ui.Model
to be extra clear, please don't consufe this with MVC Model) into the controller and use it to pass data returned by service/application layer (MVC Model) into the view. We can also pass the instance of the Model (org.springframework.ui.Model
) object directly into service layer by the means of method arguments, or ThreadLocals, or by some other way, and achieve 'True MVC'. But people don't usually do it, because it couples Application Logic (MVC Model) and the View (this is the drawback of MVC that MVP attempts to solve).MVP pattern
Overall, JavaFX/FXML is very flexible. It has poverful event handling and data binding functionalities, so you can go fully event driven and end up with MVVM (one might argue that JavaFX/FXML follows MVVM by default). Or you can be more traditional and end up with MVP, you can also start exposing your JavaFX data bindings into the core app and end up with a blend of MVC and MVP, but traditioanlly JavaFX/FXML follows MVP. Just because JavaFX uses the word "Controller" doesn't mean it follows MVC. The same is true for Angular framework, for example. Angular follows MVVM, but it uses the term "Controller" to refer to the ViewModel.
And one last thing, it's not mandatory to have ViewInterface in your app for it to follow MVP;)
Upvotes: 0
Reputation: 435
As an Android developer, I always use MVP pattern in my applications. MVC compared to MVP seems so old to me, so when I started working on a new Java app, I felt a little bit lost.
fxml
files create the UI, without specifying a controller, because you don't need one.Create the Java interfaces (IView, IPresenter and so on..)
Implement the IPresenter interface
in the Presenter class
, as you would do normally (do http requests, query a DB..)
Now the interesting part:
Let's see some code:
Create your GUI (for example a Main GUI) and implement your View interface
public class MainGUI extends Application implements MainContract.View {
public static void main(String... args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
//here we will load fxml or create the ui programmatically
}
//method from view interface
@Override
public void onServerResponse(String message) throws IOException {
//update the view
}
Now the last step:
To do this, we first create an istance of our presenter:
private MainContract.Presenter presenter;
public MainGUI() {
presenter = new MainPresenter(this);
}
this
is, of course, the MainContract.View
implemented in the MainGUI class
Now we have to get a reference to the view components
private ComboBox<Double> mySimpleList;
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("layout_main.fxml"));
Parent root = loader.load();
mySimpleList= (ComboBox<Double>) loader.getNamespace().get("mysimplelist_id");
...
primaryStage.setScene(new Scene(root, -1, -1));
primaryStage.show();
I prefer using fxml
files instead of creating the ui by code, but the logic behind is identical.
Set the items
...
mySimpleList.setItems(ValuesFactory.getMyValues());
And the listener
...
mySimpleList.valueProperty().addListener(simpleListListener);
What is simpleListListener
?
A simple ChangeListener
, where we finally call a presenter method
simpleListListener = (ChangeListener<Double>)
(observable, oldValue, newValue) -> presenter.doTheLogic(newValue);
This is an easy scenario, but in principle this is how we can use MVP Pattern with JavaFX. I also understand that it isn't the definitive solution, so I hope that one day there will be more docs where I can learn more about this argument!
Let me know if I wasn't clear in some part of the code
Upvotes: 3
Reputation: 3407
JavaFX has been designed to work with the MVC pattern. Hence it is much easier to use MVC than MVP. In MVP Presenter is responsible for formatting the data to be displayed. In JavaFX, it is done automatically by View. Here's a quick overview of JavaFX MVC:
Model - the domain data / data structure that you work with in your application (e.g. Person, Employer, Coursework, etc)
View - the UI definition of the application and its Model. The preferred way of creating a view is via an FXML
file, which is essentially the View in JavaFX MVC.
Controller - the bridge between Model and View. The code is typically isolated in XController
class (where X is the name of the FXML
View). The instance of Controller is automatically injected by FXMLLoader
or can be done manually in case you require a custom Controller. The Controller
class will have access to UI (View) elements in order to be able to manipulate different properties and also the Model, so that it can perform operations based on the UI (View) input.
To sum up, in JavaFX you don't need to have class View
, the View definition should be entirely in the FXML
file. All UI elements should be injected with @FXML
into your Controller
class. If you absolutely have to use MVP, then AWT/Swing or MVP4j - http://www.findbestopensource.com/product/mvp4j might be a better option.
For more detailed explanation please have a look at the official Oracle tutorial for JavaFX: http://docs.oracle.com/javase/8/javafx/get-started-tutorial/jfx-overview.htm
If you require help building UI using FXML
: http://docs.oracle.com/javase/8/javafx/api/javafx/fxml/doc-files/introduction_to_fxml.html
This tutorial covers basics of MVC in JavaFX and how each component communicates with others: http://code.makery.ch/library/javafx-8-tutorial/part1/
Upvotes: 9