MVnC architecture for Swing GUIs
Rather than put our "application logic" in a "messy" view class, we create a separate "controller" class, with event handlers.
We wish this controller class to be as neat and tidy as possible eg. with minimal boilerplate or much else besides our application logic.
Let's explore how we might achieve this, using an annotation-driven application framework, with some AOP and convention-over-configuration.
A part of "Gooey Beans, a trilogy in 42 parts"
Please submit your comments and suggestions for discussion below. This is an ideas-in-progress, without an implementation (yet). As such this article should be considered to be a first exploratory draft of a design-in-progress...
Next month, i'll whip up some kinda prototype, if it's deemed worth it, and if i'm still unemployed ie. with time on my hands.
| Gooey MVnC Guidelines Cheatsheet | |||
| View | Controller | Model beans | |
| Code | Messy | Neat | Trivial |
| Tool | GUI Designer | ||
| Rules | No logic | No strings | |
| Automation | Beans Binding | Events & Tasks | Validation |
| Tricks | Resource injection | AOP | |
Our controller class includes annotations in order to enable our framework
infrastructure to automatically map events from our GUI components
to event handler methods, and to support background tasks and EDT-switching
via AOP.
Annotations in our model beans, eg. User, relate to binding and validation,
where we wish to support automatic binding of view components to bean
properties, eg. by matching component names to bean property names.
Code Snippet
public class LoginController extends GBasicController {
@View LoginView view = new LoginView(); // JPanel with components
@FormBean User user = new User(); // for form fields auto binding
...
@BackgroundTask void fetchUsers() throws DatabaseException {
... // long running task
}
@BackgroundTaskDone void fetchUsersDone() {
... // update GUI with results from task
}
@EventHandler void okActionPerformed() {
... // handle OK button pressed
}
@EventHander void usernameEntered() throw DataException {
... // validate username exists in database
view.password.requestFocusInWindow();
}
...
}





