Chapter 15

GUI Development Using the Visual J++ Resource Wizard

by David Hanley


CONTENTS

In Chapter 14, "An Introduction to GUI Programming," you learned how to create graphical user interfaces in Java. You did so by creating and subclassing the AWT classes provided with the Java language. The chapter describes the classes available and includes sample programs to demonstrate how to piece together these components to create a functioning program.

You learned something else as well: Creating user interfaces manually is not easy. Creating even a simple interface takes quite a bit of code and is an error-prone endeavor. Also, looking at these user interfaces, you might be unsatisfied with their appearance. The user interfaces work, to be sure, but they are not as visually appealing as the interfaces that users have come to expect from professional programs. A user might pass up your Java program for a non-Java program with a slicker interface.

What is the reason for this design quality gap? Programmers in other, older languages have had access to tools with which they could draw the interfaces that they desired. A program would then save this drawing of the user interface in a format typically called a resource file. When the program was executing and the user interface was needed, it would be loaded from the disk and presented to the user.

These tools have not been available for Java because of the relative newness of the language, as well as the fact that resource files are typically platform specific. Resources created on, say, a Macintosh will not look good on a Windows machine, and vice versa.

Fortunately, Visual J++ solves this problem. Microsoft has leveraged its development tools for other languages and created a program that lets you draw the user interfaces you desire. Next a Java class that creates the window can be generated. Finally, the generated Java class can be added to the project and invoked to create the window.

This technique is much easier than laying out a window by hand. In addition, changing the layout is easy; instant feedback shows you how the modified layout will look. With Visual J++, an experienced graphic layout artist with no experience programming Java can design/redesign attractive forms for use in the program.

Of course, you will have to accept a few trade-offs. For example, you are limited to what has been provided for you to draw, so you cannot use the full flexibility of the AWT classes. However, you can play some "tricks" with the AWT, which you cannot do with the layout manager.

You cannot use the layout managers to make your designs adjust to the available window size, but if you lay out a window using the grid bag layout and then resize it, the components will adjust to the new window size. This type of flexibility is very important in Java because portable Java programs may run on a variety of platforms with varying resolutions and font sizes. On the whole, however, being able to draw the interfaces you want to use seems to be a good idea, and it is definitely a technique that the programmer should use.

Creating a Login Dialog

In this section you will learn how to create a login dialog that accepts a name and password to verify a user.

In the empty Visual J++ desktop, select File | New. New is a blanket term in this environment for creating new entities such as files, projects, and resources.

Visual J++ gives you the option of creating several kinds of files. Choose the option Resource Template from this list and click OK (see Figure 15.1).

Figure 15.1 : Creating a new resource.

When this operation is complete, you will see a resource template that resembles Figure 15.2.

Figure 15.2 : A blank Java resource template.

Select Insert and then Resource. You will see a list of resources (see Figure 15.3) that can be created and placed in the dialog. In this case you will be creating a dialog, so double-click this entry from the list.

Figure 15.3 : The list of resources you can choose from.

The next window gives you an area on which to draw and a toolbar that presents the items (Java visual components ) that you can draw onto the window. The combination of the two is collectively referred to as the forms designer. The forms designer will have already placed two buttons in the window (see Figure 15.4), but you can easily remove them or change their names.

Figure 15.4 : A new dialog box with its default buttons.

The area on which you can draw can be resized to the dimension that you want your dialog to occupy, both before and during construction of your interface. Try this now: Click on the lower-right corner of the gray window, hold down the mouse button, and move the mouse around. You can control the shape of the dialog.

Now try a few simple actions:

Your window should now resemble the window in Figure 15.6.

Figure 15.6 : The dialog box after the buttons are moved.

Now do the following to complete the creation of the dialog:

  1. Select the Static text button, which appears in the upper-right corner of the toolbar in these figures (use the View | Toolbars menu selection and select controls to make the controls visible), and draw two labels along the left edge of the dialog, evenly spaced. The top label should contain the text User and the bottom one should contain the text Password. You can change the label by right-clicking the labels once they are drawn and changing the contents of the Label field, or you can start typing the text for the new label, which will also bring up the Text Properties dialog box.
  2. Select the text field (or edit box) tool and draw two text fields adjacent to these labels. The text fields should be quite wide but similar in height to their corresponding labels.
  3. Double-click the bottom text field (the one associated with the Password label) and select Styles. Check the box labeled Password (see Figure 15.7).
    Figure 15.7 : Changing the style properties of the Password text box.

  4. Click the switch icon in the lower-left corner of the screen.

Visual J++ will simulate your component actually executing. Your screen should look like Figure 15.8.

Figure 15.8 : A preview of your dialog box.

Now that you have designed your first dialog, let's quickly review some of the available components and their major settings available through the various design dialogs. For a complete discussion of these components, see Chapter 14.

Component Properties

You can change the behaviors of the components by setting their properties. For example, you make the text field associated with password display only asterisks when it is filled in by using the Edit Properties dialog. This makes the field suitable for entering passwords or other sensitive data.

Button Properties

Double-click on the Buttons icon to display the now-familiar Push Button Properties window. You can set a number of properties in this window, including

In the special properties section, you get the following properties:

Text Field Properties

Text fields are the primary way users can enter text into the graphical display, and they have a number of settings.

A text field allows the user to input a single line of text. Here are some of its features:

Check Box and Radio Button Properties

Check boxes and radio buttons also have some important properties that can be set by the user.

A check box can be either on or off:

Combo Box Properties

You can also set the properties of combo boxes:

List Boxes

List boxes, like combo boxes, allow the selection of selections, but they look different and offer more options:

Static Text (Labels)

Although the user has no direct interaction with the static text, it is a critical component of the visual layout because it identifies the displayed components and guides the user:

Integrating Designed Forms into Applications

Now that you have had some experience designing forms and have learned some of the ways controls can be manipulated, you are ready to put the forms into your applications. Of course, you will need to write code to carry out the internal action of the program, and you will have to tie the code that you have written to the forms you have designed. Here is some sample code to get you started:


import java.awt.*;

class FormTest extends Frame

{

    FormTest()

    {

        show();

    }



    public static void main( String [] args )

    {

        new FormTest();

    }

}

First, create a Java application workspace and import this file into it. Compile and run it. Your display should resemble Figure 15.9.

Figure 15.9 : The results of the FormTest code.

Now create a new resource template and save it into the same directory as the FormTest code example. Choose Insert and select Files into Project. When the file selection dialog box appears, select Files of resource type and pick the resource template you created.

Now that the resource template has been inserted into the project, you can design a form to insert into your program. Select your new resource template (the default name is Templ1; the actual name will be the one you used to save the resource template), click Insert on the top menu bar, and select Resource. When the resource selection comes up, choose Dialog. You will once again be presented with the dialog starting point. In this sample, you create a class registration dialog:

Your dialog should resemble the dialog in Figure 15.10.

Figure 15.10 : How the student registration might look.

With experience and some practice, designing this screen will take only a few minutes. Creating this layout by hand would be very difficult and would have taken much longer.

The next step is to integrate the object into your program. Choose Tools and select Java Resource Wizard. Then select Browse, the template file you created, and Finish. The next dialog tells you that several files have been created.

Select Insert, choose Files into Project, and insert these files into the project. Now you have the files necessary to display the dialog you have drawn.

Integrating the Generated Classes

The job of integrating the code is not complete until you utilize the created classes.

The classes that Visual J++ creates are designed to interact with your classes, but they are not intended to be modified. This approach enables you, the programmer, to modify all your code without touching the generated code. Also, the code can be regenerated without interfering with the code that you have written. The downside is you have to write more code, but since the Resource Wizard already supplied you with dozens of lines of computer-designed code, you still come out ahead.

The class that the forms designer generates will look pretty much like the following:


    import java.awt.*;

import DialogLayout;



public class IDD_DIALOG1

{

    Container    m_Parent       = null;

    boolean      m_fInitialized = false;

    DialogLayout m_Layout;



    // Control definitions

    //--------------------------------------------------------------------------

    Button        IDOK;

    Button        IDCANCEL;

    Label         IDC_STATIC1;

    Label         IDC_STATIC2;

    Label         IDC_STATIC3;

    TextField     IDC_EDIT1;

    TextField     IDC_EDIT2;

    Checkbox      IDC_CHECK1;

    Checkbox      IDC_CHECK2;

    Label         IDC_STATIC4;

    Choice        IDC_COMBO1;

    Label         IDC_STATIC5;

    Choice        IDC_COMBO2;





    // Constructor

    //--------------------------------------------------------------------------

    public IDD_DIALOG1 (Container parent)

    {

        m_Parent = parent;

    }



    // Initialization.

    //--------------------------------------------------------------------------

    public boolean CreateControls()

    {

        // CreateControls should be called only once

        //----------------------------------------------------------------------

        if (m_fInitialized || m_Parent == null)

            return false;



        // m_Parent must be extended from the Container class

        //----------------------------------------------------------------------

        if (!(m_Parent instanceof Container))

            return false;



        // Since a given font may not be supported across all platforms, it

        // is safe to modify only the size of the font, not the typeface.

        //----------------------------------------------------------------------

        Font OldFnt = m_Parent.getFont();

        if (OldFnt != null)

        {

            Font NewFnt = new Font(OldFnt.getName(), OldFnt.getStyle(), 8);



            m_Parent.setFont(NewFnt);

        }



        // All positions and sizes are in dialog logical 

        // units, so we use a

        // DialogLayout as our layout manager.

        //----------------------------------------------------------------------

        m_Layout = new DialogLayout(m_Parent, 217, 124);

        m_Parent.setLayout(m_Layout);

        m_Parent.addNotify();



        Dimension size   = m_Layout.getDialogSize();

        Insets    insets = m_Parent.insets();



        m_Parent.resize(insets.left + size.width  + insets.right,

                        insets.top  + size.height + insets.bottom);



        // Control creation

        //----------------------------------------------------------------------

        IDOK = new Button ("OK");

        m_Parent.add(IDOK);

        m_Layout.setShape(IDOK, 34, 103, 50, 14);



        IDCANCEL = new Button ("Cancel");

        m_Parent.add(IDCANCEL);

        m_Layout.setShape(IDCANCEL, 117, 103, 50, 14);



        IDC_STATIC1 = new Label ("Name", Label.LEFT);

        m_Parent.add(IDC_STATIC1);

        m_Layout.setShape(IDC_STATIC1, 7, 27, 36, 12);



        IDC_STATIC2 = new Label ("Miskatonic university student registration.", Label.LEFT);

        m_Parent.add(IDC_STATIC2);

        m_Layout.setShape(IDC_STATIC2, 36, 7, 142, 13);



        IDC_STATIC3 = new Label ("Student ID", Label.LEFT);

        m_Parent.add(IDC_STATIC3);

        m_Layout.setShape(IDC_STATIC3, 7, 44, 32, 12);



        IDC_EDIT1 = new TextField ("");

        m_Parent.add(IDC_EDIT1);

        m_Layout.setShape(IDC_EDIT1, 45, 24, 99, 14);



        IDC_EDIT2 = new TextField ("");

        m_Parent.add(IDC_EDIT2);

        m_Layout.setShape(IDC_EDIT2, 45, 42, 99, 13);



        IDC_CHECK1 = new Checkbox ("Night classes");

        m_Parent.add(IDC_CHECK1);

        m_Layout.setShape(IDC_CHECK1, 148, 45, 55, 11);



        IDC_CHECK2 = new Checkbox ("Conflicts allowed");

        m_Parent.add(IDC_CHECK2);

        m_Layout.setShape(IDC_CHECK2, 148, 58, 62, 14);



        IDC_STATIC4 = new Label ("Special selections", Label.LEFT);

        m_Parent.add(IDC_STATIC4);

        m_Layout.setShape(IDC_STATIC4, 153, 35, 57, 8);



        IDC_COMBO1 = new Choice ();

        m_Parent.add(IDC_COMBO1);

        m_Layout.setShape(IDC_COMBO1, 7, 71, 46, 12);



        IDC_STATIC5 = new Label ("Student level", Label.LEFT);

        m_Parent.add(IDC_STATIC5);

        m_Layout.setShape(IDC_STATIC5, 7, 60, 45, 10);



        IDC_COMBO2 = new Choice ();

        m_Parent.add(IDC_COMBO2);

        m_Layout.setShape(IDC_COMBO2, 72, 71, 46, 12);



        m_fInitialized = true;

        return true;

    }

}

You can learn a few things by looking at this class:

The next step is to modify the frame class to construct the dialog creation object that has been written for you and to call its CreateControls() method. The constructor function should now look like the following:


IDD_Dialog builder;

    FormTest()

    {

        setFont( new Font( "Helvetica" , Font.PLAIN , 18 ) ); 

        builder = new IDD_DIALOG1( this );

        builder.CreateControls();

        show();

    }

setFont is required because all the measurements in the J++-generated IDD_DIALOG class are based on font size. If there is no font, there will be a lot of dividing by zero errors. Compilers hate that and will make your life miserable until you fix it. You also need to note that no matter how large you make the font, the Resource WizardÐgenerated code will set it back to 8, as shown in the following excerpt from IDD_DIALOG1:


Font OldFnt = m_Parent.getFont();

    if (OldFnt != null)

    {

        Font NewFnt = new Font(OldFnt.getName(), OldFnt.getStyle(), 8);

        m_Parent.setFont(NewFnt);

    }

This has the effect of resetting the size of any font you have set to 8. This might be a good place to violate the rule about changing the generated source code if you need larger fonts.

Upon executing this code you should see the dialog in Figure 15.11.

Figure 15.11 : The registration program executing.

Although you have now created the desired visual display, you can't interact with it yet. You can use the paradigm introduced in Chapter 14, testing the target of the action method against the handles you have to the objects. However, you need to access these widgets through the handle to the IDD_DIALOG object, which is, incidentally, why you made this object global to your function. You should also fill up the choice boxes you created. After making these modifications, your program should look like the following:


import java.awt.*;



//

// This program is a test of the classes you

// can create with the forms designer and

// an example of how you can interact with them.

//

class FormTest extends Frame

{

    IDD_DIALOG1 builder;



    FormTest()

    {

        setFont( new Font( "Helvetica" , Font.PLAIN , 18 ) );

        builder = new IDD_DIALOG1( this );

        builder.CreateControls();



        //

        //fill the class levels into the combo boxes

        //

        builder.IDC_COMBO1.addItem( "Freshman" );

        builder.IDC_COMBO1.addItem( "Sophmore" );

        builder.IDC_COMBO1.addItem( "Junior" );

        builder.IDC_COMBO1.addItem( "Senior" );

        builder.IDC_COMBO1.addItem( "Graduate" );



        //

        //fill the terms into the combo boxes

        //

        builder.IDC_COMBO2.addItem( "Winter" );

        builder.IDC_COMBO2.addItem( "Fall" );

        builder.IDC_COMBO2.addItem( "Summer (ugh)" );



        //

        // Now that you're done, show the window.

        //



        show();

    }



    //

    // create the object.

    //



    public static void main( String [] args )

    {

        new FormTest();

    }



    //

    // This is a dummy object that does nothing now,

    // but might be filled in to look in the database

    // and register the student into the classes

    // if available.  Along the way, it might open

    // more dialog boxes that would be created

    // with the forms designer.

    //

    void RegisterStudent( String name , String id ,

        String level , String term ,

        boolean night_ok , boolean conflict_ok )

    {

    }



    //

    //This handles the button clicks.  In the

    //case of the 'ok' button being clicked, it

    //pulls out the information filled into the

    //fields and passes it to a registration

    //method.

    //



    public boolean action( Event e , Object o )

    {

        if ( e.target == builder.IDOK )

        {

            RegisterStudent(

                builder.IDC_EDIT1.getText() ,

                builder.IDC_EDIT2.getText() ,

                builder.IDC_COMBO1.getSelectedItem() ,

                builder.IDC_COMBO2.getSelectedItem() ,

                builder.IDC_CHECK1.getState() ,

                builder.IDC_CHECK1.getState()

            );

            dispose();

        }



        //

        // In thic case, the window just goes away.

        //

        if ( e.target == builder.IDCANCEL )

        {

            dispose();

        }

        return true;

    }

}

A Side-by-Side Comparison

Let's compare the interface of one of the fairly unattractive programs from the last chapter-the coffee shop program-to a program that you create in the forms builder. This section explains in broad terms how to redesign the interface from the coffee shop example.

One extra trick-changing the IDs of the controls you create to names that describe their functions-makes the programming task easier. The IDs from the last program were hard to remember, and their functions are not obvious from looking at the code. The way to make this modification is to change the ID property of the component (see Figure 15.12).

Figure 15.12 : Setting the properties of elements of the coffee shop.

You can see the redesigned form in Figure 15.13. Note how much cleaner it is than the original Java coffee shop form in Chapter 14.

Figure 15.13 : The coffee shop.

Summary

This chapter examines the tools that Visual J++ provides to the programmer to automate the creation of graphical user interfaces for Java programs. You have seen the advantages of creating an interface using the Resource Wizard as opposed to hand building the required Java.