Skip to main content

Group Layout Therapy

Posted by evanx on November 30, 2006 at 6:09 AM PST

We use GroupLayout
to assemble simple subpanels.
For complicated forms, programming layout becomes (very) difficult,
and so it's saner to use a GUI designer such as Netbeans.

href="http://aptframework.dev.java.net/gooey/groupLayout.html">
align="left" hspace="8"/>

style="text-decoration: none;">



Demo

Our Address Form is in play again.


Launch

  (AddressForm, 150k/400k, unsandboxed, Java6)

addressFormLayout.png width="700" height="332" />

addressFormLayout600.png width="600" height="307" />
-->

src="http://weblogs.java.net/blog/evanx/archive/addressFormGroupLayout700.png" width="700" height="308" />


Code glance

We configure our component properties in AddressFormPanelProperties
so that AddressFormLayoutPanel below is relatively neat.

public class AddressFormLayoutPanel extends JPanel {
    AddressFormPanelProperties properties =
        dependencyContainer.getInstance(AddressFormPanelProperties.class);
       
    public AddressFormGroupLayoutPanel() {
        initComponents();
    }
   
    private void initComponents() {
        addVerticalPanel(
                createHorizontalPanel(
                createInputComponentPanel(properties.firstName, firstName),
                createInputComponentPanel(properties.lastName, lastName),
                createInputComponentPanel(properties.email, email, true),
                createInputComponentPanel(properties.phone, phone)
                ),
                createHorizontalPanel(
                createInputComponentPanel(properties.address1, address1, true),
                createInputComponentPanel(properties.address2, address2, true)
                ),
                createHorizontalPanel(
                createInputComponentPanel(properties.postalCode, postalCode),
                createInputComponentPanel(properties.city, city),
                createInputComponentPanel(properties.state, state, true),
                createInputComponentPanel(properties.country, country),
                createInputComponentPanel(properties.postable, postable)
                )
                );
    }
    ...
    private JTextField firstName = new JTextField();
    private JTextField lastName = new JTextField();
    private JTextField phone = new JTextField();
    private JTextField email = new JTextField();
    private JTextField address1 = new JTextField();
    private JTextField address2 = new JTextField();
    private JTextField city = new JTextField();
    private JTextField state = new JTextField();
    private JTextField postalCode = new JTextField();
    private JComboBox country = new JComboBox(new Object[] {"South Africa", "Zimbabwe"});
    private JCheckBox postable = new JCheckBox();
}

where createInputComponentPanel() creates a subpanel with an input component
and it's label above it.


Punchline

Our AddressFormLayoutPanel and its AddressFormLayoutPanelProperties
is delibrately interchangeable with a form produced using Netbeans' GUI designer
so that we can choose to program our form view as above, or otherwise
design our form using Netbeans.


Sneak Preview

The next step is beans binding for our form, woohoo!

Our Presentation Model
class is a separate testable class which we bind
to our form. Our controller is also implemented
as a separate class, which interacts with the components in our forms,
and of course our presentation model beans.

So to summarise, our MVC architecture consists of the following.

  • View classes eg. produced using Netbeans GUI designer.

  • Presentation Model classes which can be developed using TDD.

  • Controller class which implements event listeners
    and manipulates the view and model.

We provide beans binding support,
so that the controller can conveniently invoke a single method to update a
presentation model from a form, and visa versa.

The controller needs to manipulate the components in the view eg.
setEnabled(), requestFocusInWindow() et cetera.
Since Netbeans makes our components private to the form, we
provide proxies that are bound to the actual components using reflection.
We call them "adapters" because they give JTextField, JComboBox et al,
a unified interface eg. QInputComponent. These adapters support the binding
of the components to the presentation model.

Separating the view and controller in this fashion is fairly tedious,
but hopefully enables separation of concerns, and improves
testability eg. where we can mock up our view
to facilitate the test-driven development of our controller. This
is something i know nothing about, but i suspect is well important!?

Anyway, here is a sneak preview.


Launch

  (PersonInfo, 150k/400k, unsandboxed, Java6)

src="http://weblogs.java.net/blog/evanx/archive/personalInfoForm700.png" width="700" height="338" />

You can refresh the "BeanInfo" tab (and also the "Console" tab) to see that the
values entered into our form are written to our Presentation Model.

In this demo, we use QLayout which is GroupLayout therapy for simple subpanels.


style="text-decoration: none;">


style="text-decoration: none;">


Related Topics >>