-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Code JavaFX
Tobias Diez edited this page Dec 12, 2016
·
20 revisions
The goal of the MVVM architecture is to separate the state/behavior from the appearance of the ui. This is archived by dividing JabRef into different layers, each having a clear responsibility.
- The Model contains the business logic and data structures. These aspects are again encapsulated in the logic and model package, respectively.
- The View controls the appearance and structure of the UI. It is usually defined in a FXML file.
- View model converts the data from logic and model in a form that is easily usable in the gui. Thus it controls the state of the View. Moreover, the ViewModel contains all the logic needed to change the current state of the UI or perform an action. These actions are usually passed down to the logic package. The important aspect is that the ViewModel contains all the ui-related logic but does not have direct access to the controls defined in the View. Hence, the ViewModel can easily be tested by unit tests.
- The Controller initializes the view model and binds it to the view. In an ideal world all the binding would already be done directly in the FXML. But JavaFX's binding expressions are not yet powerful enough to accomplish this. It is important to keep in mind that the Controller should be as minimalistic as possible. Especially one should resist the temptation to validate inputs in the controller. The ViewModel should handle data validation!
The only class which access model and logic classes is the ViewModel. Controller and View have only access the ViewModel and never the backend. The ViewModel does not know the Controller or View.
More details about the MVVM pattern can be found in an article by Microsoft.
- The view model should derive from
AbstractViewModel
.
public class MyDialogViewModel extends AbstractViewModel {
}
- Add a (readonly) property as a private field and generate the getters according to the JavaFX bean conventions:
private final ReadOnlyStringWrapper heading = new ReadOnlyStringWrapper();
public ReadOnlyStringProperty headingProperty() {
return heading.getReadOnlyProperty();
}
public String getHeading() {
return heading.get();
}
- Create constructor which initializes the fields to their default values. Write tests to ensure that everything works as expected!
public MyDialogViewModel(Dependency dependency) {
this.dependency = Objects.requireNonNull(dependency);
heading.set("Hello " + dependency.getUserName());
}
- Add methods which allow interaction. Again, don't forget to write tests!
public void shutdown() {
heading.set("Goodbye!");
}
public class AboutDialogController extends AbstractController<AboutDialogViewModel>
@FXML protected Button closeButton;
@FXML protected ImageView iconImage;
@Inject private DialogService dialogService;
@FXML
private void initialize() {
viewModel = new AboutDialogViewModel(dialogService, clipBoardManager, buildInfo);
}
- The initialize method may use data-binding to connect the ui-controls and the
ViewModel
. However, it is recommended to do as much binding as possible directly in the FXML-file.
helloLabel.textProperty().bind(viewModel.helloMessageProperty());
@FXML
private void openJabrefWebsite() {
viewModel.openJabrefWebsite();
}
The view consists of two parts:
- a FXML file "MyDialog.fxml" which defines the structure and the layout of the UI. It is recommended to use a graphical UI builder like JavaFX SceneBuilder to edit the FXML file.
- a
View
class that loads the FXML file. For dialogs this amounts to deriving fromAbstractDialogView
. The fxml file is loaded automatically using the same name as the class. To make this convention-over-configuration approach work, both the FXML file and the View class should have the same name and should be located in the same package.
public class MyDialogView extends AbstractDialogView
@Override
public void show() {
FXDialog aboutDialog = new FXDialog(AlertType.INFORMATION, Localization.lang("About JabRef"));
aboutDialog.setDialogPane((DialogPane) this.getView());
aboutDialog.show();
}
- Home
- General Information
- Development
- Please go to our devdocs at https://devdocs.jabref.org
- GSoC 2025 ideas list
- Completed "Google Summer of Code" (GSoC) projects
- GSoC 2024 ‐ Improved CSL Support (and more LibreOffice‐JabRef integration enhancements)
- GSoC 2024 - Lucene Search Backend Integration
- GSoC 2024 ‐ AI‐Powered Summarization and “Interaction” with Academic Papers
- GSoC 2022 — Implement a Three Way Merge UI for merging BibTeX entries
- GSoC 2021 - Improve pdf support in JabRef
- GSoC 2021 - Microsoft Word Integration
- GSoc 2019 - Bidirectional Integration — Paper Writing — LaTeX and JabRef 5.0
- GSoC Archive
- Release
- JabCon Archive