----------------------
----------------------

 Tutorial


Before we even get started, you will still need to understand the basics of the JGoodies Form Layout manager in order to be effective with this tool. If you understand the principle of that manager, then you will feel right at home. That tool can be found here. There is a PDF document that will explain the basics of the layout manager.

For our tutorial, we will build a simple Customer dialog box that will have the following components...

  • Name JGoodies Separator
  • Surname JLabel
  • Surname JComboBox
  • First Name JLabel
  • First Name JTextField
  • Last Name JLabel
  • Last Name JTextField
  • Suffix JLabel
  • Suffix JComboBox
  • Contact JGoodies Separator
  • Home Phone JLabel
  • Home Phone JTextField
  • Work Phone JLabel
  • Work Phone JTextField
  • Fax JLabel
  • Fax JTextField
  • Email JLabel
  • Email JTextField
  • Orders JGoodies Separator
  • Order JTable
  • JGoodies ButtonBar with OK and Cancel Buttons

So let's discuss the best way to get off the ground with this tool and build the example is to run the executable jar. There are two jars, one that is executable (formLayoutBuilderx.jar) and one that simply has the builder itself (formLayoutBuilder.jar). The latter should be used in your project in conjunction with the JGoodies forms jar file. The executable jar includes the JGoodies stuff for those who just want an easy executable jar just to test drive the tool. By the way, the code for this project is written using JDK 1.5 but uses Toby Reyelt's Retroweaver tool that takes 1.5 class files and converts them to 1.4. You will not be able to compile the code without JDK 1.5.

java -jar formLayoutBuilderx.jar

The basic paradigm is that you have a set of row specs and column specs that form a grid. You add components by clicking in the grid and clicking the New button above the table. You can also add rows and columns and delete components using the buttons there. Try to construct the Customer Screen to look like the following image. You will have to add rows, move components, etc.

Customer Screen

Here is how I did it. This may help you a bit...

builder

Questions and answers...

Q: How do I insert a component?
A: Click the cell in the component table where you want to add a component and click the 'New' Button

Q: How do I make the separator go all the way across?
A: Click the separator component in the table and increase the Column Span property

Q: What is the best way to build the buttons?
A: Create a JGoodies ButtonBar, type 'right' in the alignment property, and use the properties given to add buttons

Q: Why do my labels right align?
A: Because the column definition is right:max(30dlu:pref). Look in the JGoodies docs to see what this means...

Q: I can't find a component I created. How do I find it?
A: Go to the Show Component combobox and select your component, it will be highlighted.

Q: How do I insert a row or column?
A: Click in the table and hit the 'Add Row Before', 'Add Row After', 'Add Column Before', or 'Add Row After' buttons.

Q: How can I move a component around in the grid?
A: Click on the component in the table and use the Position arrows to move it around.

Q: How can I make a component stretch to fill the cell?
A: Click on the component in the table and set the Horizonal or Vertical Alignment properties to 'Fill'.

Q: How can I remove a component?
A: Click on the component in the table and the click the trash can icon.

Q: Can I add another panel and lay it out too?
A: Yes, just add a JPanel component. You will see another constraints tab you can use to layout the subpanel.

Q: How do I set the title on the frame?
A: You can do this with code later

Q: How do I make the JLabels PLAIN instead of BOLD?
A: You can do this with code later using UIManager

So now you have the form looking the way you want. What now. Well, let's first save the xml file out to where you want to create the Java file for the dialog. Choose File | Save As and save the xml file. It will look something like this xml file.

You will notice that all this really does is capture the row and column constraints, the names and constraints of your components. Now let's look at the code that the tool creates. Click File | View Code. The code looks something like the following...

    // here are declarations for the controls you created
   
javax.swing.JComboBox suffixCombo = new javax.swing.JComboBox () ;
    javax.swing.JLabel lastNameLabel =
new javax.swing.JLabel ( "Last Name" ) ;
    javax.swing.JTextField firstNameText =
new javax.swing.JTextField () ;
    javax.swing.JTextField lastNameText =
new javax.swing.JTextField () ;
    javax.swing.JTextField faxText =
new javax.swing.JTextField () ;
    java.awt.Component contactSeparator = DefaultComponentFactory.getInstance
() .createSeparator ( "Contact Info" ) ;
    javax.swing.JLabel surnameLabel =
new javax.swing.JLabel ( "Surname" ) ;
    javax.swing.JButton okButton =
new javax.swing.JButton ( "OK" ) ;
    javax.swing.JButton cancelButton =
new javax.swing.JButton ( "Cancel" ) ;
    java.awt.Component buttonBar = ButtonBarFactory.buildRightAlignedBar
( new JButton [] { okButton,cancelButton }) ;
    javax.swing.JLabel workPhoneLabel =
new javax.swing.JLabel ( "Work Phone" ) ;
    javax.swing.JTextField workPhoneText =
new javax.swing.JTextField () ;
    javax.swing.JTextField emailText =
new javax.swing.JTextField () ;
    javax.swing.JTextField homePhoneText =
new javax.swing.JTextField () ;
    javax.swing.JLabel faxLabel =
new javax.swing.JLabel ( "Fax Number" ) ;
    java.awt.Component ordersSeparator = DefaultComponentFactory.getInstance
() .createSeparator ( "Orders" ) ;
    javax.swing.JComboBox surnameCombo =
new javax.swing.JComboBox () ;
    java.awt.Component nameSeparator = DefaultComponentFactory.getInstance
() .createSeparator ( "Name" ) ;
    javax.swing.JLabel suffixLabel =
new javax.swing.JLabel ( "Suffix" ) ;
    javax.swing.JLabel emailLabel =
new javax.swing.JLabel ( "E-mail" ) ;
    javax.swing.JLabel homePhoneLabel =
new javax.swing.JLabel ( "Home Phone" ) ;
    javax.swing.JLabel firstNameLabel =
new javax.swing.JLabel ( "First Name" ) ;
    javax.swing.JTable orderTableControl =
new javax.swing.JTable () ;
    javax.swing.JScrollPane orderTable =
new javax.swing.JScrollPane ( orderTableControl ) ;

   
// here is where we load the layout constraints.  change the xml filename!!!
   
LayoutConstraintsManager layoutConstraintsManager =
       LayoutConstraintsManager.getLayoutConstraintsManager
( this .getClass () .getResourceAsStream ( "yourConstraintFile.xml" )) ;

   
// here we add the controls to the container.  you may
    // need to change the name of panel
   
panel.add ( suffixCombo, "suffixCombo" ) ;
    panel.add
( lastNameLabel, "lastNameLabel" ) ;
    panel.add
( firstNameText, "firstNameText" ) ;
    panel.add
( lastNameText, "lastNameText" ) ;
    panel.add
( faxText, "faxText" ) ;
    panel.add
( contactSeparator, "contactSeparator" ) ;
    panel.add
( surnameLabel, "surnameLabel" ) ;
    panel.add
( buttonBar, "buttonBar" ) ;
    panel.add
( workPhoneLabel, "workPhoneLabel" ) ;
    panel.add
( workPhoneText, "workPhoneText" ) ;
    panel.add
( emailText, "emailText" ) ;
    panel.add
( homePhoneText, "homePhoneText" ) ;
    panel.add
( faxLabel, "faxLabel" ) ;
    panel.add
( ordersSeparator, "ordersSeparator" ) ;
    panel.add
( surnameCombo, "surnameCombo" ) ;
    panel.add
( nameSeparator, "nameSeparator" ) ;
    panel.add
( suffixLabel, "suffixLabel" ) ;
    panel.add
( emailLabel, "emailLabel" ) ;
    panel.add
( homePhoneLabel, "homePhoneLabel" ) ;
    panel.add
( firstNameLabel, "firstNameLabel" ) ;
    panel.add
( orderTable, "orderTable" ) ;

At the top, you have declarations for the components you created. In the middle you have some code that shows you how to create a LayoutConstraintsManager from the xml you created, and finally, you have the code you need to add the components to the container.

So what we need to do is create a Java file called CustomerPanel in the same directory we saved the xml file. I've created one for you and it's source is included in the distribution. It looks something like this...

package org.mlc.swing.example;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

/**
*
@author Michael Connor
*/
public class CustomerPanel extends javax.swing.JPanel
{
   
javax.swing.JComboBox suffixCombo = new javax.swing.JComboBox () ;
    javax.swing.JLabel lastNameLabel =
new javax.swing.JLabel ( "Last Name" ) ;
    javax.swing.JTextField firstNameText =
new javax.swing.JTextField () ;
    javax.swing.JTextField lastNameText =
new javax.swing.JTextField () ;
    javax.swing.JTextField faxText =
new javax.swing.JTextField () ;
    java.awt.Component contactSeparator =
        com.jgoodies.forms.factories.DefaultComponentFactory.getInstance
() .createSeparator ( "Contact Info" ) ;
    javax.swing.JLabel surnameLabel =
new javax.swing.JLabel ( "Surname" ) ;
    javax.swing.JButton okButton =
new javax.swing.JButton ( "OK" ) ;
    javax.swing.JButton cancelButton =
new javax.swing.JButton ( "Cancel" ) ;
    java.awt.Component buttonBar =
        com.jgoodies.forms.factories.ButtonBarFactory.buildRightAlignedBar
( new JButton [] { okButton,cancelButton }) ;
    javax.swing.JLabel workPhoneLabel =
new javax.swing.JLabel ( "Work Phone" ) ;
    javax.swing.JTextField workPhoneText =
new javax.swing.JTextField () ;
    javax.swing.JTextField emailText =
new javax.swing.JTextField () ;
    javax.swing.JTextField homePhoneText =
new javax.swing.JTextField () ;
    javax.swing.JLabel faxLabel =
new javax.swing.JLabel ( "Fax Number" ) ;
    java.awt.Component ordersSeparator =
        com.jgoodies.forms.factories.DefaultComponentFactory.getInstance
() .createSeparator ( "Orders" ) ;
    javax.swing.JComboBox surnameCombo =
new javax.swing.JComboBox () ;
    java.awt.Component nameSeparator =
        com.jgoodies.forms.factories.DefaultComponentFactory.getInstance
() .createSeparator ( "Name" ) ;
    javax.swing.JLabel suffixLabel =
new javax.swing.JLabel ( "Suffix" ) ;
    javax.swing.JLabel emailLabel =
new javax.swing.JLabel ( "E-mail" ) ;
    javax.swing.JLabel homePhoneLabel =
new javax.swing.JLabel ( "Home Phone" ) ;
    javax.swing.JLabel firstNameLabel =
new javax.swing.JLabel ( "First Name" ) ;
    javax.swing.JTable orderTableControl =
new javax.swing.JTable () ;
    javax.swing.JScrollPane orderTable =
new javax.swing.JScrollPane ( orderTableControl ) ;

   
public CustomerPanel ()
    {
       
super () ;
        org.mlc.swing.layout.LayoutConstraintsManager layoutConstraintsManager =
            org.mlc.swing.layout.LayoutConstraintsManager.getLayoutConstraintsManager
(
               
this .getClass () .getResourceAsStream ( "customerLayout.xml" )) ;
        setBorder
( com.jgoodies.forms.factories.Borders.DIALOG_BORDER ) ;
        LayoutManager panelLayout = layoutConstraintsManager.createLayout
( "panel" , this ) ;
       
this .setLayout ( panelLayout ) ;

       
this .add ( suffixCombo, "suffixCombo" ) ;
       
this .add ( lastNameLabel, "lastNameLabel" ) ;
       
this .add ( firstNameText, "firstNameText" ) ;
       
this .add ( lastNameText, "lastNameText" ) ;
       
this .add ( faxText, "faxText" ) ;
       
this .add ( contactSeparator, "contactSeparator" ) ;
       
this .add ( surnameLabel, "surnameLabel" ) ;
       
this .add ( buttonBar, "buttonBar" ) ;
       
this .add ( workPhoneLabel, "workPhoneLabel" ) ;
       
this .add ( workPhoneText, "workPhoneText" ) ;
       
this .add ( emailText, "emailText" ) ;
       
this .add ( homePhoneText, "homePhoneText" ) ;
       
this .add ( faxLabel, "faxLabel" ) ;
       
this .add ( ordersSeparator, "ordersSeparator" ) ;
       
this .add ( surnameCombo, "surnameCombo" ) ;
       
this .add ( nameSeparator, "nameSeparator" ) ;
       
this .add ( suffixLabel, "suffixLabel" ) ;
       
this .add ( emailLabel, "emailLabel" ) ;
       
this .add ( homePhoneLabel, "homePhoneLabel" ) ;
       
this .add ( firstNameLabel, "firstNameLabel" ) ;
       
this .add ( orderTable, "orderTable" ) ;

       
// LayoutFrame frame = new LayoutFrame (layoutConstraintsManager);
        // frame.setVisible(true);
   
}

   
public static void main ( String [] args )
    {
       
UIDefaults defaults = UIManager.getDefaults () ;
        defaults.put
( "Label.font" , new javax.swing.plaf.FontUIResource ( new java.awt.Font ( "Arial" , java.awt.Font.PLAIN, 12 ))) ;
        defaults.put
( "ComboBox.background" , new javax.swing.plaf.ColorUIResource ( 255 , 255 , 255 )) ;

        CustomerPanel customerPanel =
new CustomerPanel () ;

        JFrame frame =
new JFrame ( "Edit Customer" ) ;
        frame.setDefaultCloseOperation
( JFrame.EXIT_ON_CLOSE ) ;
        frame.getContentPane
() .setLayout ( new BorderLayout ()) ;
        frame.getContentPane
() .add ( customerPanel, BorderLayout.CENTER ) ;
        frame.setSize
( 600 , 700 ) ;
        frame.setVisible
( true ) ;
   
}

We had to change a few things to go from the code that we had generated to what we see here. First of all, in the line where we instantiate a LayoutConstraintsManager, change the xml filename to the filename that you actually used. Also, there is a main method and lots of other stuff that we had to create. Another thing we did was change all of the panel.add() methods to this.add because we are actually just adding the components to this instead of something we called panel. You will have to import the JGoodies stuff if you used any of that.

At this point, you are ready to go. I would suggest a few things. First of all, create a factory method for labels and change them from bold to regular. The separators then stand out and the labels don't scream out at you. Also, create a factory method for the JComboBox because it's background color should be white like the other controls and it should be the same height as the JTextFields. JTextArea also needs a factory method that gives it a border and sets the work breaks properly.

More questions answered...

Q: What if I need to add a component that isn't in the tool?
A: No worries, just add some other component that is close in behavior so that it shows up on the screen and then change the code later.

Q: How do I modify the layout once it's already been built.
A: This is where this tool really excels over IDEs. After you set the layout on your compontent, uncomment the following lines...

//LayoutFrame layoutFrame = new LayoutFrame(layoutConstraintsManager);
//layoutFrame.setVisible(true);

When you want to run the builder again, just uncomment these lines. When you run your program, the builder will also show up and you can make changes, save the new xml file, and get code for any components you may have added. I think it would be cool to create an environment variable that would signal your panels provide a button that when clicked would pop up the builder. By doing this, you could change the layouts of your application while it is running.