EarthWeb sites:
|
|
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.
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:
- Double-click the OK button, and a pop-up window that lets
you set pushbutton properties will appear. Click in the Caption
text box and replace the word OK with login. Then
close the Push Button Properties window. (See Figure 15.5.)
Figure 15.5 : Setting the properties of the button.
- Click the new Login button and hold down the mouse button.
Drag the Login button to the bottom of the window, toward the
left, and leave it there. Similarly, drag the Cancel button to
the bottom, but move it toward the right.
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:
- 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.
- 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.
- 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.
- 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.
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
- Visible-This setting is on by default; if you turn
off the Visible property, you can still see the button
as you are designing it, but it will be invisible when the window
is utilized.
- Disabled-A disabled button will be visible (though
in a ghosted fashion to make clear its disabled state), but the
user will not be able to interact with the button. This setting
can be useful for dialog boxes in which certain options are not
currently available, but might be available in other situations.
In the special properties section, you get the following properties:
- Icon & Bitmap-These settings allow you to use
an image for the graphical display of the button. For example,
an OK button might have a bitmap with OK in big letters and a
check mark used for its image.
- Client edge & Static edge-These settings refer
to edges that add a slightly different style to a button, drawing
attention to a particular button or indicating how a group of
buttons should be associated logically.
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:
- AutoHScroll-If this option is enabled and the user
types in more text than can fit in the text field, the text in
the field will move to the left, making space for the user to
type in more text. Later, the user can move through the text field
with the arrow keys. If this option is disabled, once the cursor
reaches the right edge of the text field, no more text can be
entered. Therefore, disabling this setting might be useful when
you want to limit the length of strings entered.
- Password-When this option is enabled, text that is
typed into the field will not be displayed. Rather, asterisks
(or some other character) will be displayed to represent the characters
the user has entered. This option prevents bystanders from observing
the text of passwords as they are being entered.
- Read Only-With this option enabled, the user cannot
enter text into the text field. This option might be used to "lock"
certain entries in place after some option has been picked or
to achieve a desired visual effect.
- Want Return-When this option is activated, an event
will be sent to the target window when the Enter key is pressed
inside this text field. This feature can be very desirable. For
example, in a login menu, if the user presses Enter after entering
the password, you would like to process the login request instead
of forcing the user to click the OK button.
- Uppercase & Lowercase-This setting changes text
that is entered in a field into either uppercase or lowercase,
despite what the user tries to enter.
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:
- Left Text-This option places the text on the left
of the component area, with the actual check box on the right.
This arrangement is the inverse of the normal ordering of components.
- Push-like-This gives a check box a button-like appearance,
while preserving the semantics of a check box. Although the state
is no longer explicitly displayed, you can change the label of
the button to reflect its altered state.
- Icon & Bitmap-These options allow images to be
used for check box labels.
Combo Box Properties
You can also set the properties of combo boxes:
- Sort-If Sort is on, the entries of the combo
box will be sorted. Sorting can help the user find a desired entry.
- Items-At drawing time, you can enter the list of
items that the combo box will display.
List Boxes
List boxes, like combo boxes, allow the selection of selections,
but they look different and offer more options:
- Selection-This option lets you choose between single
and multiple. In the single-selection scheme, when an item is
selected, any item that was previously selected becomes unselected.
In the multiple-selection scheme, a new selection does not replace
an old selection. Rather, you must click a selected item again
to turn it off.
- Disable no scroll-When a list has more items than
will fit in the list box, a scrollbar is formed to allow the user
to move through the list. Normally, if the display area can accommodate
the entire list, the scrollbar will go away. If this setting is
selected, however, the scrollbar will not go away. You might want
to use this setting when you have several list boxes with differing
amounts of content and you want to maintain a uniform look. (They
will not look the same if some have default scrollbars and others
do not.) Also, having a scrollbar appear as a user is adding items
to a list might not be what the user expects.
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:
- Sunken & Border-These settings change the appearance
of labels, making them stand out more from the surrounding screen.
- Align text-The text that you enter can be left aligned,
right aligned, or centered in the area that you have drawn.
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:
- The class registration should take a name and an ID number.
By setting the ID number field's property to Password, you can
prevent the actual ID from being displayed.
- Students should enter the appropriate class level and the
term for which they are registering. These items should be implemented
as choice components.
- Students should be able to enter special requests, such as
desiring night classes or not minding intentional conflicts.
- The dialog box should contain a number of text fields in which
students enter their desired class list.
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.
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:
- You must pass the handle of a container to this class. The
constructed components and attributes are then applied to this
parent container.
- Simply constructing this object does nothing for the parent;
you must call CreateControls() to actually insert the
controls into the parent.
- This class utilizes a standard class named DialogLayout.
In this particular framework, DialogLayout can be shared
among several dialog components. You must also include DialogLayout
in any distribution of your code. DialogLayout is a standard
class that is included in Visual J++.
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;
}
}
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.
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.
|