I have a pet project which is a 2D game engine.
After creating all the backend functionality, I want to implement a UI for it.
My current plan is to do this via MVC because it strikes me as the most feasible way of doing this (logic first, then UI).
Now, I am unsure how to design/implement this with either Swing or JavaFX, as I do not yet fully understand what the underlying concepts of either are.
Can someone describe to me how to implement MVC with Swing or JavaFX?

- 201
- 3
- 15
-
1[The MVC pattern and Swing](https://stackoverflow.com/questions/5217611/the-mvc-pattern-and-swing). – George Z. Apr 12 '20 at 10:34
1 Answers
You can have a model that is a general one can be used by different views.
To demonstrate it let's first introduce a interface that can be used to listen to such model:
//Interface implemented by SwingView and used by Model
interface Observer {
void observableChanged();
}
Consider a very simple model, with one attribute only: an integer value between 0 and a certain max:
//Generic model. Not dependent on the GUI tool kit. Use by Swing as well as JAvaFX
class Model {
private int value;
private static final int MAX_VALUE = 100;
private Observer observer;
int getValue(){
return value;
}
void setValue(int value){
this.value = Math.min(MAX_VALUE, Math.abs(value));
notifyObserver();
}
int getMaxValue() {
return MAX_VALUE;
}
//-- handle observers
void setObserver(Observer observer) {
this.observer = observer;
}
private void notifyObserver() {
if(observer != null) {
observer.observableChanged();
}
}
}
Note that the model calls observer.observableChanged()
when value
changes it.
Now let's use this model with a Swing
gui that displays a random number :
import java.awt.*;
import java.util.Random;
import javax.swing.*;
//Swing app, using a generic model
public class SwingMVC {
public static void main(String[] args) {
new SwingController();
}
}
//SwingController of the MVC pattern."wires" model and view (and in this case also worker)
class SwingController{
public SwingController() {
Model model = new Model();
SwingView swingView = new SwingView(model);
model.setObserver(swingView); //register view as an observer to model
update(model);
}
//change model
private void update(Model model) {
Random rnd = new Random();
//use swing timer so the change is performed on the Event Dispatch Thread
new Timer(1000,(e)-> model.setValue(1+rnd.nextInt(model.getMaxValue()))).start();
}
}
//view of the MVC pattern. Implements observer to respond to model changes
class SwingView implements Observer{
private final Model model;
private final JLabel label;
public SwingView(Model model) {
this.model = model;
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setLayout(new GridBagLayout());
label = new JLabel(" - ");
label.setFont(new Font(label.getFont().getName(), Font.PLAIN, 48));
label.setHorizontalTextPosition(SwingConstants.CENTER);
frame.add(label);
frame.pack();
frame.setVisible(true);
}
@Override
public void observableChanged() {
//update text in response to change in model
label.setText(String.format("%d",model.getValue()));
}
}
We can use the very same model and achieve the same functionality with a JavaFx
gui:
import java.util.Random;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
//JavaFa app, using a generic model
public class FxMVC extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
FxController fxController = new FxController();
Scene scene = new Scene(fxController.getParent());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}
class FxController{
private final FxView view;
FxController() {
Model model = new Model();
view = new FxView(model);
model.setObserver(view); //register fxView as an observer to model
update(model);
}
//change model
private void update(Model model) {
Random rnd = new Random();
//use javafx animation tools so the change is performed on the JvaxFx application thread
PauseTransition pt = new PauseTransition(Duration.seconds(1));
pt.play();
pt.setOnFinished(e->{
model.setValue(1+rnd.nextInt(model.getMaxValue()));
pt.play();
});
}
Parent getParent(){
return view;
}
}
//View of the MVC pattern. Implements observer to respond to model changes
class FxView extends StackPane implements Observer{
private final Model model;
private final Label label;
public FxView(Model model) {
this.model = model;
label = new Label(" - ");
label.setFont(new Font(label.getFont().getName(), 48));
getChildren().add(label);
}
@Override
public void observableChanged() { //update text in response to change in model
//update text in response to change in model
label.setText(String.format("%d",model.getValue()));
}
}
On the other hand, you can have a model that is more specific, intended to be used with a specific tool-kit, and gain some advantages by using some tool of that tool kit.
For example a model made using JavaFx
properties, in this example SimpleIntegerProperty
, which simplifies the listening to model changes (does not make use of the Observer
interface):
import java.util.Random;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
//JavaFa app, using a JavaFx model
public class FxApp extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
FxController fxController = new FxController();
Scene scene = new Scene(fxController.getParent());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}
class FxAppController{
private final FxAppView view;
FxAppController() {
FxAppModel model = new FxAppModel();
view = new FxAppView(model);
update(model);
}
//change model
private void update(FxAppModel model) {
Random rnd = new Random();
//use javafx animation tools so the change is performed on the JvaxFx application thread
PauseTransition pt = new PauseTransition(Duration.seconds(1));
pt.play();
pt.setOnFinished(e->{
model.setValue(1+rnd.nextInt(model.getMaxValue()));
pt.play();
});
}
Parent getParent(){
return view;
}
}
//View does not need to implement listener
class FxAppView extends StackPane{
public FxAppView(FxAppModel model) {
Label label = new Label(" - ");
label.setFont(new Font(label.getFont().getName(), 48));
getChildren().add(label);
model.getValue().addListener((ChangeListener<Number>) (obs, oldV, newV) -> label.setText(String.format("%d",model.getValue())));
}
}
//Model that uses JavaFx tools
class FxAppModel {
private SimpleIntegerProperty valueProperty;
private static final int MAX_VALUE = 100;
SimpleIntegerProperty getValue(){
return valueProperty;
}
void setValue(int value){
valueProperty.set(value);
}
int getMaxValue() {
return MAX_VALUE;
}
}
A Swing
gui and a JavaFx
gui, each uses a different instance of the same Model
:

- 18,467
- 6
- 33
- 65
-
So, regarding animation, which one would you suggest? Going Swing or going JavaFX? – Snorik Apr 12 '20 at 15:46
-
1You may find [this](https://stackoverflow.com/questions/16694948/swing-vs-javafx-for-desktop-applications) helpful. – c0der Apr 13 '20 at 04:09