views:

558

answers:

5

I'm just starting my first Java Swing project(doing mainly web-based apps before) and try to understand how to build a proper architecture with separation of concerns between the MVC components.

Just about any documentation I find goes very deep into the details of how each and every Swing UI widget works and can be used, but all examples just directly call program logic from a Class that extends, for example, JPanel - which seems odd and no good architecure.

It would be best if that would be IDE-independent, but if such things come into play, it should be said that in the overall project, we have already Eclipse, JFormdesigner and JGoodies in use.

I also see that JSR296 defines a framework that seems to address my concerns. Should I just use something that implements it?

+1  A: 

The Java Tutorial has a Swing trail that is very good for getting the concepts straight.

If you are used to web apps, you will find the GUI-model rather confusing until you have this straight.

http://java.sun.com/docs/books/tutorial/uiswing/

Thorbjørn Ravn Andersen
Sure I saw that :) but it falls in the mentioned category: telling me lots of detals about every widget( no doubt this will be good to see at some point, and there are some more interesting things to find there!), but I'm looking to get the architecture right!
Henning
+5  A: 

This is an area of Java programming that is highly under-documented. As you mention, extending from JFrame or JDialog to develop a GUI is not a good design practice, yet you see it all over the place in sample code.

JSR 296 is a useful starting place, but it's architecture has some serious problems. I do use JSR 296, but I have my own flavor of it, and consistently have to work around issues introduced by the framework design.

I've long thought that there should be a discussion group/wiki/something focused on this topic. So far, I've found the listserv for various rich client libraries to be useful, but not comprehensive. Something to think about starting maybe, in my free time :-)

So I can't provide any definitive resources for best practices in building swing applications. But I can give you some pointers to the toolkits and concepts that I've found that I use over and over again. Maybe these will be useful to you as you get going. Also, if enough people are interested in having a discussion about best practices, sharing code, etc... I'd be interested in being part of it.

First, some absolutely critical libraries if you are going to do Swing development:

  1. Binding - there are a number of libraries that do this (JGoodies, JSR295 which has spun off into an open source project called Better Beans Binding (BBB), Eclipse binding framework). I started years ago using JGoodies, but I have moved over to using BBB because I find it's approach to be more intuitive. I can't stress the advantages of the declarative coding approach that binding allows for - it will truly revolutionize your code

  2. AppFramework (or some flavor thereof) - JSR 296 is the place to start here. As I mentioned above, it has some problems - if you do use JSR296, I strongly, strongly recommend that you try to avoid using the singleton that is at the core of the framework (other than as a source for injection of the framework components that you actually need).

  3. GlazedLists - if you are doing anything in the UI that involves lists, tables or trees, you should take a hard look at GlazedLists. It's an incredible project (not just for Swing apps, but it really shines in that arena)

  4. Validation - JGoodies has a very good validation library. Learn it, use it, be one with it. Real time validation is an incredibly important part of a modern Swing app.

  5. MigLayout - The Mig layout manager is the best around. I strongly advise against the temptation of using an IDE GUI builder - learn MigLayout (it will take a couple of hours, tops), and code things up by hand.

So those are the key, absolutely must-have libraries in my book.

Now some concepts:

A. Presentation Model - Martin Fowler has a lot of info on this design pattern. Long and short, it separates behavior from presentation at the GUI level. IF you are used to MVC, Presentation Model adds another layer of separation that is quite important to 'live' UIs. All of my views are backed by a corresponding presentation model. The end result is that the view code is really, really simple - focusing on two things: 1. Layout, and 2. Binding view components to the presentation model. That's it.

B. Views are NOT subclasses of JPanel. Instead, I follow the JGoodies inspired technique of treating the View as a builder that creates JPanels. The basic pattern is:

public class MyView{
  private MyPresentationModel model;

  private JButton okButton;
  private JButton cancelButton;
  ...

  public MyView(MyPresentationModel model){
    this.model = model;
  }

  public JPanel buildView(){
    initComponents(); // this method actually creates the okButton and cancelButton objects
    bindComponentsToModel(); // this method binds those objects to the PresentationModel
    JPanel p = new JPanel(new MigLayout());
    p.add(...);
    ...
    return p;
  }
}

This approach, followed religiously, allows incredibly rapid development of UIs that are easy to maintain. Note that we can use a given View to construct multiple JPanels that are all backed by the same PresentationModel - changes in one panel generated by the view will immediately be visible in another panel generated by the same view.

C. Use Actions not event handlers. JSR 296 actually does a good job of making Actions easy to create and work with.

D. Do long running operations (even something that takes 100ms) off of the EDT. JSR 296 makes this fairly easy with it's Task support - but there are a number of gotchas in 296's Task system when it comes to exception handling. If you have property changes that in turn result in long running events, be sure you think carefully about which thread those changes are going to occur on. Using Tasks is a big change to how you do development, but it's a really important area for any real Swing application - take the time to learn about it.

E. Resource injection is important. Use it from the beginning (instead of telling yourself that you'll add it later) - if you find yourself calling setText() on a JLabel, it's time to sit back and call setName() instead, and add an entry to the resources file. JSR 296 makes this pretty easy to do if you are disciplined about it.

I think that's enough for now - this is a highly complex subject with lot's of nuance. I've spent the past 7 or 8 years banging my head into things that don't work - and I'm continually finding better ways to do even the things that work well for me.

Kevin Day
One other thing that I want to mention here: I have looked extensively at the Eclipse, NetBeans and Spring rich client platforms. My take away is that they might be useful for some types of projects, but the learning curve is steep, and you really have to play by their rules if you choose to use one of those platforms.
Kevin Day
What's wrong with extending JPanel (or any JComponent)? If I have, for example, a panel that's purpose is to show a map, I will create a class called MapPanel, extend JPanel, and draw a map on the panel.
Thomas Owens
no problem with that usage at all, Thomas - The issue I have is the scenario where folks sub-class JPanel so they can add components to it (extending from JFrame or JDialog is an even better example - I'll edit the post to indicate that). In your case, if you placed the map inside a JScrollPane, then added the JScrollPane to the panel, then I'd say that a different approach was warranted. But for creating a truly new UI component, extending JPanel is the way to go.
Kevin Day
thanks kevin, that's a lot stuff to look into! I thin, if we were about to start a project from scratch, eclipse/netbeans/spring would be nice - probably a bit fatter that AppFramework. But as I have to add stuff to an existing code base (of which the creator himself is not sure if it's architected properly), I need something that can fit into this, and still be properly designed as far as possible.
Henning
I hear you. The idea of using an RCP framework as a baseline was really appealing - but my first read through of how to use NetBeans to build RCP apps filled me with horror (the number of code smells *required* by the framework was just aweful). App Framework has problems as well, but at least it's possible to build an application 'correctly' using it. Eclipse RCP would probably have been ok, but the deployment alone is so huge that we just couldn't go down that path.
Kevin Day
+1  A: 

Martin Fowler has started a development on his Patterns of Enterprise Application Architecture book covering some patterns that were not covered in the original book, including GUI patterns.

Although its contents are not exclusively Java oriented, they are very valuable.

Reginaldo
thanks for those - I'll check them out!
Henning
Fowler's work has been incredibly helpful in my development as a GUI developer. Highly recommended once you get to a point where you can abstract your thinking about GUI development to a design pattern level. Presentation Model is insanely useful.
Kevin Day
A: 

You can try the Spring Rich Client project. I have a very good experience with the rest of the spring portfolio.

David Rabinowitz
Thanks! I knew of it and will look at it sooner or later. But first, I want to learn from scratch how to do it properly, then I have to integrate some new functionality into an existing codebase (and eventually refactor this base on the go). So the full-blown frameworks might not be what I can use now.
Henning
A: 

Another very basic, very simple howto showing things about this is there:

http://www.macs.hw.ac.uk/guidebook/?name=Using%20The%20GUI&page=1

I'm not sure if I like the idea of the Controller itself implementing ActionListener - on the other hand, if it wouldn't, I'd need an extra class for this, which again would need to know the controller and tell him things...

Maybe the problem is just that there are so many possible choices of how Swing components can communicate with a controller, and none of them looking really "right" at the first glance...

Henning