views:

195

answers:

5

I am writing an application that requires a large amount of swing GUI components. I am having a lot of trouble organizing the class. Is there a methodology to organize and neatly layout class architecture?

I find my constructor confusing it consists of many components being initialized followed by several event handlers.

In addition, I have numerous anonymous and inner classes and my main class has become bloated. However, when I put the inner class event handlers in separate files I have trouble accessing the components of my main class. Is there a methodology to internally organize large swingGUI applications?

A: 

Swing is internally organized using the MVC pattern.

Carlos Tasada
+1  A: 

I'd split things up into JPanels.

Take a group of components that are related to each other, and make a new class (in a seperate file) that inherits from JPanel. Then in your Main class, you just import that class and use it like any other JPanel except it has all the components inside it already. The Main class would only need to add the panels to the layout.

In the JPanel class you can do all your initialization, configuration, and event listening in just that class so you don't clutter up your Main class.

jonescb
I'm assuming I would make each custom JPanel components public but the actual custom JPanel private in the main class?
No, you extend JPanel in the class. So the class _is_ a JPanel. You just do MyCustomPanel mcp = new MyCustomPanel(); and add(mcp);You wouldn't have an explicit JPanel object in the class. The 'this' object will be an implicit JPanel object.
jonescb
However, if I want to access the components within the myCustomPanel I would need to make their components public?
+3  A: 

If your large amount of GUI components are arranged within separate panels, with the panels then laid out in your frame, you can methodize the creation of those inner panels to make the code easier to digest:

public MyApp() {
    JPanel mainPanel = new JPanel(new BorderLayout());
    JPanel north = createNorthPanel();
    mainPanel.add(north, BorderLayout.NORTH);

    JPanel south = createSouthPanel();
    mainPanel.add(south, BorderLayout.SOUTH);

    JPanel east = createEastPanel();
    mainPanel.add(east, BorderLayout.EAST);

    JPanel west = createWestPanel();
    mainPanel.add(west, BorderLayout.WEST);

    myFrame.setContentPane(mainPanel);
}
akf
I like this solution and definitely solves my bloated constructor, however it does not help the class overall.
This is perfect for a small program. +1
+2  A: 

In larger swing projects I do partinioning of the app like that:

  • Have one class per GUI element like JPanel,JDialog etc.

  • Use a separate package for each screen, especially if you have to implement customized TableModels or other complex data structures

  • Don't use anonymous and inner classes, implement instead an ActionListener and check ActionEvent.getActionCommand() in there.

stacker
This is the best solution. However, for a small project it will be a significant amount of extra work.
@Mac- and you just figured out why there is no one solution for every project. I like to borrow from Einstein: "keep it as simple as possible, but no simpler". If everything in the constructor works for your small project, use it. However, if you find that the project is no longer small and things are getting unwieldy, start using some design patterns to help out. akf's solution is a good first step, and stacker's solution would be one step farther. The problem with going with stacker's solution from the beginning is that it actually makes things worse for small projects, as you have noted.
Nemi
A: 

Here are the strategies I used in the past to reduce clutter in swing classes.

  1. Generic Listener: instead of sprincling anonymous ActionListener classes around create one ActionListener, which takes an object and the name of a method as a constructor parameter. When triggered the ActionListener calls the specified method on the specified object. Adds complexity in form of reflection, but burns hundreds of lines of errorprone boilerplate code.

  2. Separation of Concerns. Have separate [Methods|Classes|Packages] for the following tasks:

    • creating Components: You need a new Textfield? Don't directly call new JTextField, let a factory create it for you. Inside the creation Method you do all the settings like preferred size, colors, fonts. Structures code, removes duplication and makes sure that thing behave the same way all over the application. Pays of especially for complex controls like date pickers

    • assemble simple controls to units that belong together: lable + edit control + marker for invalid input; Sets of buttons

    • layout of a bunch of such unit to one JPanel

    • Pluging together of the JDialog, JWindow, JFrame or whatever and the JPanel

    • wiring of events

  3. Consider JGoodies Binding

Jens Schauder