Single Screen Tutorial - Allan-Jacobs/Swing-MVC GitHub Wiki
Before starting
This tutorial will walk you through creating an app with Swing-MVC. Setup maven, and add the repo and dependency on the readme before starting this tutorial.
A little about Swing-MVC
Swing-MVC is a lightweight framework for building multi-screen apps, but it can also make single screen apps. It helps by separating of a screen logic into three parts: the Model, the View, and the Controller. This is known as the MVC pattern. At runtime, Swing-MVC searches the classpath for your classes and constructs screens from it.
Registering screens
To register a screen, you need to do two things. The first is to extend
the abstract classes and implement the methods for Model
, View
and Controller
.
The second is to add the @MVC
annotation to each of your classes with the name of
the screen they create.
// ExampleModel.java
// import necessary classes
import com.redstoneblocks.java.swing_mvc.MVC;
import com.redstoneblocks.java.swing_mvc.core.Model;
// annotate the class with @MVC("EXAMPLE")
// to tell Swing-MVC that this class belongs to the
// "EXAMPLE" screen. This is case sensitive.
@MVC("EXAMPLE")
public class ExampleModel extends Model {
// declare, but not initialize, the variables;
// we are using package-private for our model variables
// because these components will normally be in
// a package together
int count;
// state is data that can be passed from the previous screen.
// we can ignore it as we are not using it.
@Override
public void init(Object state) {
// initialize the data
count = 0;
}
}
// ExampleView.java
// import necessary classes
import com.redstoneblocks.java.swing_mvc.MVC;
import com.redstoneblocks.java.swing_mvc.core.View;
// annotate the class to tell Swing-MVC that this
// class belongs to the "EXAMPLE" screen
@MVC("TEST")
public class ExampleView extends View {
// declare, but not initialize the variables here
// these are package-private to allow easier access in
// the controller.
JPanel gui;
JButton incrementButton;
JButton decrementButton;
JLabel countLabel;
@Override
public void create(Model model) {
// due to java's type system, we pass in the model
// as a `Model` and cast it to the correct type (ExampleModel).
ExampleModel exampleModel = (ExampleModel) model;
// we initialize the components here
gui = new JPanel();
incrementButton = new JButton("Increment");
decrementButton = new JButton("Decrement");
// here we also use data from the model
// to construct the JLabel with a default value
count = new JLabel(String.valueOf(exampleModel.count));
// now we add everything to the JPanel
gui.add(increaseButton);
gui.add(decreaseButton);
gui.add(count);
}
// this is used so that Swing-MVC can display
// the view in the window.
@Override
public JPanel getGui() {
return gui;
}
}
// ExampleController.java
// import necessary classes
import com.redstoneblocks.java.swing_mvc.EntryPoint;
import com.redstoneblocks.java.swing_mvc.MVC;
import com.redstoneblocks.java.swing_mvc.core.Controller;
import com.redstoneblocks.java.swing_mvc.core.Model;
import com.redstoneblocks.java.swing_mvc.core.View;
import com.redstoneblocks.java.swing_mvc.util.Navigator
import java.awt.event.ActionEvent;
// we annotate the controller with the `@EntryPoint`
// annotation to tell Swing-MVC that this screen is
// the entry point. This annotation can be on any of
// the extended classes (ExampleModel, ExampleView, ExampleController)
// or all of them, but it needs to be on at least one
@EntryPoint
// we annotate the controller with @MVC("EXAMPLE") to tell
// Swing-MVC that it belongs to the "EXAMPLE" screen.
@MVC("EXAMPLE")
public class ExampleController extends Controller {
// these are simply the model and view,
// but casted already, so you do not need
// to cast them everytime you use them
ExampleView exampleView;
ExampleModel exampleModel;
// Navagator is a utility class for changing
// screens (navigating). It also allows you
// to pass data to the next screen's Model.
// you may store it in a variable.
@Override
public void init(Navigator nav) {
// here we create action listeners for the buttons
// we increment or decrement count, and then update the label
exampleView.decrementButton.addActionListener(e -> {
exampleModel.count--;
exampleView.countLabel.setText(String.valueOf(exampleModel.count));
});
exampleView.incrementButton.addActionListener(e -> {
exampleModel.count++;
exampleView.countLabel.setText(String.valueOf(exampleModel.count));
});
}
// this method is run before navigating to cleanup any resources
// that the controller is using, such as network connections or
// unsaved files. since we don't need to cleanup anything,
// we keep it empty
@Override
public void cleanup() {}
}
Running the app
The App class is what finds and runs your screens. All you need to do is run the App#createAndStart method in your application's entry point.
// Run.java
// import App class
import com.redstoneblocks.java.swing_mvc.runner.App;
public class Run {
public static void main(String[] args) {
// this runs your app
App.createAndStart();
}
}
Compile and run your app. You will see a window popup with 2 buttons and a label, and you can increment or decrement the count.