http://www.developer.com/lang/article.php/3589961/Building-Java-GUIs-with-Matisse-A-Gentle-Introduction.htm
It is a curiosity that when Java was first introduced, it made a name (some would say "became synonymous with") simple interactive GUIs and animations in applets embedded on Web pages. It was the first foothold for the language. At the time, the GUI construction was simpler than a lot of the alternatives out there (it was the time of Motif, windows 3.1 and does anyone remember NeWS?). It was also a little limiting—AWT provided a decent way of getting a few buttons and menus put into an applet or even a Java application if you were ambitious, but the results were fairly limited and simple. To combat this and bring the possibility of richer desktop applications and a higher abstraction to GUI building in Java, Swing was created. Swing learned much from other GUI toolkits available at the time and brought in a lot more flexibility... and some more complexity. Fast forward to a year ago and the state of the art for Swing creation revolved around numerous layout managers, the most flexible (and notorious) being the GridBagLayout. This is an amazing layout manager that lets you control just about every aspect of every widget placement in every form. The problem is, it requires you to. Netbeans, and various other IDEs, already had good support to help with creating grid bag layouts, but these usually involved a different view of the UI from the WYSIWYG one, and it takes a while to learn all the controls and settings even in these helper tools. In NetBeans 5.0, however, a new option is available. Matisse is a new GUI builder that uses the GroupLayout manager. This is a new layout manager that is not a part of standard Swing (yet), but can be freely distributed with your application. Matisse is Java UI building done right. It is familiar, offers drag and drop placement, and sensible defaults that can still be altered and overridden easily for flexibility. It is a GUI builder as easy to use (with a couple of minor exceptions—more on those later) as Visual Basic, but has a huge advantage over VB in that the resulting forms and panels can be re-sized in a meaningful way, without having to write all sorts of resize event handling code. This article will outline some of the new features in Matisse and is intended to give you a taster of what is possible with it. It details a real application (albeit very small and simple) that I recently wrote to solve a real-world need. My hope is that this will demonstrate what is possible with Matisse, and whet your appetite to find out more. I will also point out that I am not generally a Swing or even a GUI developer. I may commit atrocities in this article from a UI perspective and, if I do, apologies. However, my point here is to show that anyone can use Matisse to make an application—even a server-side hacker like me. Before following along with this article, you will need to grab NetBeans IDE 5.0 from http://www.netbeans.org/ and install it. I also recommend reading or printing out the Matisse GUI Builder Legend at http://www.netbeans.org/kb/50/quickstart-gui_legend.html; it provides a handy cheat sheet of what the various guidelines mean when creating a GUI in Matisse. The source code for this example can be downloaded from here. You may or may not be aware, but I am co-host of a podcast all about Java called the Java Posse along with three other guys (Tor Norbye, Carl Quinn, and Joe Nuxoll). We record at least once a week and have adopted the approach of everyone recording their own microphone feed, and then mixing the results into a single audio file using a multi-track audio editor. This produces great results, but also takes a fair chunk of time. The longest part of the editing process is removing the mistakes or "Flubs" as we call them. This can be long pauses, words that are tripped over, more than one of us talking at the same time, and so forth. Because we are not audio professionals, and are using skype (with the inherent lag), there tends to be quite a lot of these. As a result, I try and capture these flubs as they happen. To start with, I just wrote them down, with a rough time, but this took too long and too much attention. So, I decided to write a simple GUI app to make the job easier, and to spit out the results in the correct format for Audacity labels, which is the multitrack editor I use to edit the shows. The format for the labels file in Audacity is very simple. It consists of a start time and end time, in seconds (with decimal fractions), and then a text table. To keep my "flubber" application simple, I make the start and end time the same, so markings refer to an instant, not a time period. Also my labels are simply a counter, starting at 1 and counting up (this way I don't miss any when scrolling through the audio). So, my file might look like this: My flubber application (or jflubber as I call it, to avoid any legal issues with Robin Williams) is a simple way of starting a clock, marking flub points as instantaneous moments of time, and spitting out these moments as a text file that can be loaded into Audacity. Simple, but useful and effective. Okay. Now it's time to build jFlubber. First, you need to create a Java Application, so fire up NetBeans 5.0 and: Now for the fun part. You will paint your UI using Matisse. First, you need a new form: Your GUI needs a text label, five buttons, and a text area. The buttons are: The text label will be at the top and will show the current time elapsed since the start button was pressed, in minutes and seconds. Why not hours, minutes, and seconds? Why not microseconds? Well, because I prefer minutes and seconds. You are, of course, free to format this stopwatch display however you like. The text area will hold the flub points formatted in the Audacity label format. It's not strictly necessary to see this, but it is a nicety to be able to get visual feedback when a flub point is added. To see what you are aiming towards, the finished UI should look like this: To create this UI in Matisse, first set up the time label: That seems like a lot of steps, but that's because I took the description very deliberately. In fact, with a little practice you will be creating and placing UI components very quickly and easily in Matisse. Next, you can add the buttons: Finally, you want to add the text area to hold the flub points and display them. At this point, it is a good idea to save all (in fact, Matisse is still fairly young, so I recommend saving a lot just as a precaution). Again, try resizing the form in the GUI editor to make sure everything re-sizes as you would expect. You have constructed your new GUI. To give it a test, you need to add a little code to the main class to cause it to be displayed: Close down the running application if it is still up. It's time to add some functionality to the buttons. The main trick left to demonstrate with Matisse is hooking up the buttons. The rest is simply filling in code, and because this will be a very long article if I go into all of the code in great detail, I will provide all of the code snippets and some brief descriptions, but won't go into enormous detail in this area. Suffice it to say that the backing code is fairly straightforward and should not be surprising to anyone who takes a little time to understand it. Also, again for brevity, I will put all of the code into the Form Class you created. This is fine for a small app, but in a larger app you will want to think carefully about how you lay out your code for maintainability and good coding practices. One thing you will need for this app is a timer thread that, once the clock is started, keeps updating the timer label periodically with the elapsed time of the recording. You also need a few new attributes for this, so select JFlubberMainFrm.java in the editor, and then click on the Source view near the top of the edit window so that you can see the Java source. Then, add the following code right after the public class JFlubberMainFrm extends javax.swing.JFrame {: This code defines four attributes used to track the time and label number, and also a TimerTask that runs a thread that will be used later in the class to update the time label periodically once the start button is pressed. Note that this code uses the new Java 5 convenient text formatting. If you are still using Java 1.4, you will need to use a message formatter instead to get the minutes and seconds formatted nicely. After you have put in this code and saved it, you will probably see some missing class errors. Just right-click in the editor window and select Fix Imports to add in the required classes. For the TimerTask, select the java.util one rather than the swing one if asked by the Fix Imports wizard. Everything is now in place. You now can add some button event handlers: This is where my own lack of knowledge of Swing may show though. There are a lot of different events in Swing and I tend to stick with the ones I know that do what I want. Whether they are strictly speaking correct or not is another matter. In fact, this leads me to my one complaint about Matisse right now, compared with something like Java Studio Creator where you can double-click on a button and get a sensible default event generated for that button. In Matisse, you can't do this; you have to right-click and select the event you want, from a somewhat overwhelming list of options. For example, given a button, the default event I want is when someone clicks the button. In Java Studio Creator, a double-click gives me a handler for exactly this event, which is really nice and saves me time and worry. In Swing, for the button I have a choice of ActionPerformed, MouseClicked, MousePressed, MouseReleased and many, many others. I am sure there will be times I would want to use some of these other options, but by far the most common is someone clicking the button, so couldn't Matisse be made to select a logical default in this case? If it does do this already, I have not yet found the magic way to do it. Instead, for buttons I tend to stick with the MouseReleased event (sort of like the MouseUp from the apple way of event handling). In other words, the event is fired not when the button is pressed, but when the button is released after being pressed. This seems to work the best and most consistently. Knowing this, adding code to the MouseReleased event on the button is pretty easy: Start Button You want to add similar handlers for the other buttons, so repeat the above steps to attach the code below to each of the buttons as named: Stop Button Flub Button Note that this method uses a method called addLabel for convenience. You have not defined it yet, so define it in the class as: Save Button You want to use this to put a filechooser up for the user to let them save the text from the text area: Clear Button This needs to set the text area to empty, and set the label count back to 0 (so that the labels start getting added from 1 again). Again, the above doesn't have a lot of explanation attached, so if you get confused as to what goes where, just take a look at the source code from the zip file included with this article and it should become apparent. Once you have added this code, saved, and fixed any import problems (Fix Imports from the editor popup menu), select build main project from the IDE build menu. When this builds, you should notice that the IDE reports that it has already wrapped the application up into a jar file for you (called jFlubber.jar in my case) and it also says that you can run the application using java -jar jFlubber.jar (with appropriate path information to tell java where jFlubber.jar is). However, that might not be the case, especially if you take the jar file created out of the dist directory and run it from somewhere else on your machine. Instead, you may see the error: If you see this, the reason is that the GroupLayout that Matisse uses is not part of the standard Java distro, and so when you try and run the jar file with a normal java distribution, the layout manager is not available. Unfortunately, the fix for this is a little ugly, and the only other real complaint I have about Matisse usage in NetBeans 5.0. One can imagine that this problem will be one that crops up for every Matisse-based GUI created, and how nice it would be to have a simple project property checkbox to say "include Matisse related classes in the distribution jar file", but if there is such an option, I have yet to find it. Instead, the fix isn't hard, but it's irritating. In a nutshell, you have to alter the ant script used to build the project and add the missing classes required. To do this: This defines a task that NetBeans calls automatically to roll the GroupLayout class into the jar file so that it will run anywhere. This is a useful thing to know for other such dependencies, without doubt, but if Matisse is going to be the way to create Java GUIs now, how much better it would be to make this step much easier with a project-level setting. Note that there is a lib folder that you can keep in the same place relative to the jar file that will also keep this working; however, most developers roll a single jar file for the java -jar type of distribution simply because it is much easier to distribute that way. Your mileage may vary. Perhaps I am way out of line for suggesting the rolling up of GroupLayout into the jar file; it's simply my preference (and it makes things run much better if you are calling the jar file in a different directory). After you make and save the change, do a Clean and Build from the Build menu; the whole thing should be rolled up with GroupLayout this time. Then, run java -jar jFlubber.jar again. So, now you should be able to run your new jFlubber application. From the IDE, just click the run button or menu entry, or you can create a .bat file or .sh file depending what operating system you are using, and run the java -jar jFlubber.jar command that way. Either way you run it, the flubber application should be running just fine. Here is a screenshot of my version running in Ubuntu 5.10 Linux: So, this little application is unlikely to win any awards, beauty contests, or just about anything else, but it does serve as a good introduction to Matisse development, and also fills a useful role in my podcasting production tools. I am certain this program could be vastly improved, which is why I stuck it out there under the GPL license, and I hope it will be useful either as an example or an actual application to others. Note also that it is a very simple application. It demonstrates only a fraction of what Matisse can do; furthermore, it doesn't even touch on the NetBeans Rich Client Platform (RCP) that will save an enormous amount of time for anyone doing more complex applications. Perhaps I will dive into the RCP in a future column, once I have got to know it better, but in the meantime I hope this example has been useful. If anyone wants to point out improvements in the way this application was written, please feel free to contact me. I am eager to learn more about Swing development now that there is finally a tool that makes it easy enough for me to be interested again. It's hard to believe that it has taken this long for a really good Swing GUI creation solution like this to come along, but I am very glad that it has. Dick Wall is a Principal Systems Engineer for NewEnergy Associates, A Siemens Company based in Atlanta, GA that provides energy IT and consulting solutions for decision support and energy operations. He can be reached for comment on this and other matters at dick.wall@newenergyassoc.com. He also co-hosts The Java Posse, a podcast devoted to Java news and the Java community, which can be found at http://javaposse.com.
Building Java GUIs with Matisse: A Gentle Introduction
March 8, 2006
Prerequisites
About the Application
1.576 1.576 1 5.121 5.121 2 83.122 83.122 3 Getting Started
Create the UI

Testing It Out
JFlubberMainFrm jFlubberFrm = new JFlubberMainFrm();
jFlubberFrm.setVisible(true);
Making It Work
The Timer Thread
private Timer timer = null;
private int labelNo = 0;
private long currTime = 0L;
private long startTime = 0L;
class UpdateTimeTask extends TimerTask {
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int)(millis/1000);
int minutes = seconds/60;
seconds = seconds % 60;
timeLabel.setText(String.format("%d:%02d", minutes, seconds));
}
}
Button Events
if(startTime == 0L) {
startTime = evt.getWhen();
timer = new Timer();
timer.schedule(new UpdateTimeTask(), 200, 200);
}
if(timer != null) {
timer.cancel();
startTime = 0L;
}
labelNo++;
this.addLabel(Integer.toString(labelNo));
public void addLabel(String label) {
long millis = System.currentTimeMillis() - startTime;
double seconds = (double)millis / 1000;
String labelList = jTextArea1.getText();
labelList = labelList + Double.toString(seconds) + "t" +
Double.toString(seconds) + "t" + label + "n";
jTextArea1.setText(labelList);
}
JFileChooser chooser = new JFileChooser();
int rVal = chooser.showSaveDialog(this);
if(rVal == JFileChooser.APPROVE_OPTION) {
File outputFile = chooser.getSelectedFile();
PrintWriter outputStream;
try {
outputStream = new PrintWriter(new BufferedWriter(
new FileWriter(outputFile)));
outputStream.print(this.jTextArea1.getText());
outputStream.close();
}
catch(IOException ex) {
ex.printStackTrace();
}
}
this.jTextArea1.setText("");
this.labelNo = 0;
Building and Distribution
Exception in thread "main" java.lang.NoClassDefFoundError:
org/jdesktop/layout/GroupLayout$Group
<target name="-post-jar">
<jar update="true" destfile="${dist.jar}">
<zipfileset src="${libs.swing-layout.classpath}"/>
</jar>
</target>
The Result

Conclusion
Further Reading/Resources
About the Author