Skip to content
Dahie edited this page Sep 13, 2010 · 3 revisions

To understand how the application is working, it is important to understand what the Swing Application Framework is doing.

General

During the production of every application comes a point where the programmer is faced with the same general problems.
How to handle resources and localization? How to handle threads? How to deal with actions and threads? What is the basic data structure, Model-View-Controller?
Most programmers develop their own solutions over time and reuse them in their programs. The disadvantages are, that for common problems, many different solutions were implemented and everybody cooked by their own recipy. Secondly, these solutions contain only the experience of one programmer and the problems he faced before. Anticipating problems is naturally difficult.

For this reason, I didn’t want to base this application on my earlier programs, but instead on a general purpose
desktop application framework. This framework was supposed to give a skeleton for the model-controller structure, resource management, thread handling and action-handling.
Appframework
developed as Specification JSR-296 by Sun. The framework was specified in 2006 and has been in development since then. It was scheduled to be included in Java7 and by 2008 it was already included NetBeans.

Action-handling

Java’s Action-Interface describes a class, which contains one specific action, that is performed by the use from somewhere in the GUI. Usual cases are menu-entries, ToolBar-entries, buttons or hotkeys. The Action-interface allows to create one class for handling. If you disable the action, this is resembled everywhere this action is used in the GUI. This makes it very easy to deal with actions.

However there are a few drawbacks. You have to implement the Interface yourself. You can still create many instances of one
action, although every Action should be treated like a Singleton. Mixing Actions with Resources can be done easily, but there are no best-practice rules.
Appframework gives straight rules on how to define and use actions. These are defined very differently.

In your project you have a view, for example a Frame of your program. Within this frame you have the menus, buttons etc, which
shall have an assigned Action. You defined this action by creating a new method, which is preceded by the Annotation @Action. Using Reflection based on the method name, the framework creates an Action-object with the method’s contents taken as the actionPerformed()-method. This object is automatically put into the ActionMap, a singleton-map, which contains all created actions of this Frame. You can identify the action by the name of the method, retrieve it from the map and simply add it to the
button like you would with your own Action-implementation. For a bit convenience I use this methods:


private javax.swing.Action getAction(String actionName) {
	ActionMap actionMap = getContext().getActionMap(ImageFlowView.class, this);
    return actionMap.get(actionName);
}

Note that the ImageFlowView describes the class we want to get the ActionMap from. In theory
you can a uniqe ActionMap for every view.
A common Action-definition in a AppView-Class could look like this:


@Action
public Task doSomething() {
	System.out.println("Print something");
	return new DoesSomethingTask();
}

@Action can have two Attributes. enabledProperty can bind the
enabled-property of the Action with a boolean-field by the same name. selectedProperty does the same for the selected-property.


boolean enabled = true;
@Action (enabledProperty = "enabled")
public Task doSomething() { ... }


Resource-Management

Every view or frame can have it’s own property-file, which contains single key-value-pairs for resources. To remain with our example. The Action we created in the section above is included in the properties-files of the frame, in which it is defined. By convention the properties-files are in a subpackage resources and by the same name as the frame. Inside the file you can use the Action’s name as key to set up different values.

The AppView.properties of our example above may look like this:

doSomething.Action.text = Paste
doSomething.Action.accelerator = shortcut V
doSomething.Action.shortDescription = Paste the Unit in the clipboard to the workflow.
doSomething.Action.icon=icon.png

This can also be used for any other kind of texts or paths.

Thread-handling

Appframework allows easy thread handling based on the SwingWorker-Classes. In a nutshell, Appframeworks let’s you create Task which encapsulates procedures. Without any thread-management this procedure would occupy the main-thread,
Tasks allow to perform it parallel in an own thread.

Tasks are written by extending the Task-class. Tasks can be used in Actions, which is one way to start them.


class DoSomethingTask<String> extends Task<String, Void> {
	protected GraphController doInBackground() throws InterruptedException {
		String facNumber = "f: ";
		for (int i = 0; i < 10;i++) { facNumber += " "+i;}
	}
}

@Action public Task<String> doSomething() {
  return new DoSomethingTask<String>();
}

The Task-class is abstract and you create your Task by overriding the necessary method doInBackground(). There are more methods to override. succeed() is called after the procedure is finished, failed, in case of problems and cancelled() in case of a cancellation by the user.