Windowed applications | CodeGuru

Windowed applications

Bruce Eckel’s Thinking in Java Contents | Prev | Next It’s possible to see that for safety’s sake you can have only limited behavior within an applet. In a real sense, the applet is a temporary extension to the Web browser so its functionality must be limited along with its knowledge and control. There are […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 1, 2001
8 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

It’s


possible to see that for safety’s sake you can have only limited behavior


within an applet. In a real sense, the applet is a temporary extension to the


Web browser so its functionality must be limited along with its knowledge and


control. There are times, however, when you’d like to make a windowed


program do something else than sit on a Web page, and perhaps you’d like


it to do some of the things a “regular” application can do and yet


have the vaunted instant portability provided by Java. In previous chapters in


this book we’ve made command-line applications, but in some operating


environments (the Macintosh, for example) there isn’t a command line. So


for any number of reasons you’d like to build a windowed, non-applet


program using Java. This is certainly a reasonable desire.

A


Java windowed application can have menus and dialog boxes (impossible or


difficult with an applet), and yet if you’re using an older version of


Java you sacrifice the native operating environment’s look and feel. The


JFC/Swing library allows you to make an application that preserves the look and


feel of the underlying operating environment. If you want to build windowed


applications, it makes sense to do so only if you can use the latest version of


Java and associated tools so you can deliver applications that won’t


confound your users. If for some reason you’re forced to use an older


version of Java, think hard before committing to building a significant


windowed application.


It’s


impossible to put a menu directly on an applet (in Java 1.0 and Java 1.1; the


Swing library


does

allow


it), so they’re for applications. Go ahead, try it if you don’t


believe me and you’re sure that it would make sense to have menus on


applets. There’s no

setMenuBar( )
method in
Applet
and that’s the way a menu is attached. (You’ll see later that
it’s possible to spawn a
Frame
from within an
Applet,
and the
Frame
can contain menus.)

There


are four different types of

MenuComponent,
all derived from that abstract class:
MenuBar
(you can have one
MenuBar
only on a particular
Frame),
Menu
to hold one individual drop-down menu or submenu,
MenuItem
to represent one single element on a menu, and
CheckboxMenuItem,
which is derived from
MenuItem
and produces a checkmark to indicate whether that menu item is selected.

Unlike


a system that uses resources, with Java and the AWT you must hand assemble all


the menus in source code. Here are the ice cream flavors again, used to create


menus:

//: Menu1.java
// Menus work only with Frames.
// Shows submenus, checkbox menu items
// and swapping menus.
import java.awt.*;
 
public class Menu1 extends Frame {
  String[] flavors = { "Chocolate", "Strawberry",
    "Vanilla Fudge Swirl", "Mint Chip",
    "Mocha Almond Fudge", "Rum Raisin",
    "Praline Cream", "Mud Pie" };
  TextField t = new TextField("No flavor", 30);
  MenuBar mb1 = new MenuBar();
  Menu f = new Menu("File");
  Menu m = new Menu("Flavors");
  Menu s = new Menu("Safety");
  // Alternative approach:
  CheckboxMenuItem[] safety = {
    new CheckboxMenuItem("Guard"),
    new CheckboxMenuItem("Hide")
  };
  MenuItem[] file = {
    new MenuItem("Open"),
    new MenuItem("Exit")
  };
  // A second menu bar to swap to:
  MenuBar mb2 = new MenuBar();
  Menu fooBar = new Menu("fooBar");
  MenuItem[] other = {
    new MenuItem("Foo"),
    new MenuItem("Bar"),
    new MenuItem("Baz"),
  };
  Button b = new Button("Swap Menus");
  public Menu1() {
    for(int i = 0; i < flavors.length; i++) {
      m.add(new MenuItem(flavors[i]));
      // Add separators at intervals:
      if((i+1) % 3 == 0)
        m.addSeparator();
    }
    for(int i = 0; i < safety.length; i++)
      s.add(safety[i]);
    f.add(s);
    for(int i = 0; i < file.length; i++)
      f.add(file[i]);
    mb1.add(f);
    mb1.add(m);
    setMenuBar(mb1);
    t.setEditable(false);
    add("Center", t);
    // Set up the system for swapping menus:
    add("North", b);
    for(int i = 0; i < other.length; i++)
      fooBar.add(other[i]);
    mb2.add(fooBar);
  }
  public boolean handleEvent(Event evt) {
    if(evt.id == Event.WINDOW_DESTROY)
      System.exit(0);
    else
      return super.handleEvent(evt);
    return true;
  }
  public boolean action(Event evt, Object arg) {
    if(evt.target.equals(b)) {
      MenuBar m = getMenuBar();
      if(m == mb1) setMenuBar(mb2);
      else if (m == mb2) setMenuBar(mb1);
    }
    else if(evt.target instanceof MenuItem) {
      if(arg.equals("Open")) {
        String s = t.getText();
        boolean chosen = false;
        for(int i = 0; i < flavors.length; i++)
          if(s.equals(flavors[i])) chosen = true;
        if(!chosen)
          t.setText("Choose a flavor first!");
        else
          t.setText("Opening "+ s +". Mmm, mm!");
      }
      else if(evt.target.equals(file[1]))
        System.exit(0);
      // CheckboxMenuItems cannot use String 
      // matching; you must match the target:
      else if(evt.target.equals(safety[0]))
        t.setText("Guard the Ice Cream! " +
          "Guarding is " + safety[0].getState());
      else if(evt.target.equals(safety[1]))
        t.setText("Hide the Ice Cream! " +
          "Is it cold? " + safety[1].getState());
      else
        t.setText(arg.toString());
    }
    else
      return super.action(evt, arg);
    return true;
  }
  public static void main(String[] args) {
    Menu1 f = new Menu1();
    f.resize(300,200);
    f.show();
  }
} ///:~ 

In


this program I avoided the typical long lists of


add( )

calls for each menu because that seemed like a lot of unnecessary typing.


Instead, I placed the menu items into arrays and then simply stepped through


each array calling


add( )

in a


for

loop. This makes adding or subtracting a menu item less tedious.

As


an alternative approach (which I find less desirable since it requires more


typing), the


CheckboxMenuItem

s


are created in an array of handles called


safety

;


this is true for the arrays


file

and


other

as well.

This


program creates not one but two


MenuBar

s


to demonstrate that menu bars can be actively swapped while the program is


running. You can see how a


MenuBar

is made up of


Menu

s,


and each


Menu

is made up of


MenuItem

s,


CheckboxMenuItem

s,


or even other


Menu

s


(which produce submenus). When a


MenuBar

is assembled it can be installed into the current program with the


setMenuBar( )

method. Note that when the button is pressed, it checks to see which menu is


currently installed using


getMenuBar( )

,


then puts the other menu bar in its place.

When


testing for “Open,” notice that spelling and capitalization are


critical, but Java signals no error if there is no match with


“Open.” This kind of string comparison is a clear source of


programming errors.

The


checking and un-checking of the menu items is taken care of automatically, but


dealing with CheckboxMenuItems can be a bit surprising since for some reason


they don’t allow string matching. (Although string matching isn’t a


good approach, this seems inconsistent.) So you can match only the target


object and not its label. As shown, the

getState( )
method
can be used to reveal the state. You can also change the state of a
CheckboxMenuItem
with
setState( ).

You


might think that one menu could reasonably reside on more than one menu bar.


This does seem to make sense because all you’re passing to the


MenuBar
add( )

method is a handle. However, if you try this, the behavior will be strange and


not what you expect. (It’s difficult to know if this is a bug or if they


intended it to work this way.)

This


example also shows what you need to do to create an application instead of an


applet. (Again, because an application can support menus and an applet cannot


directly have a menu.) Instead of inheriting from


Applet

,


you inherit from


Frame

.


Instead of


init( )

to set things up, you make a constructor for your class. Finally, you create a


main( )

and in that you build an object of your new type, resize it, and then call


show( )

.


It’s different from an applet in only a few small places, but it’s


now a

standalone
windowed application and you’ve got menus.

Dialog
boxes

A


dialog
box is a window that pops up out of another window. Its purpose is to deal with
some specific issue without cluttering the original window with those details.
Dialog boxes are heavily used in windowed programming environments, but as
mentioned previously, rarely used in applets.

To


create a dialog box, you inherit from

Dialog,
which is just another kind of
Window,
like a
Frame.
Unlike a
Frame,
a
Dialog
cannot have a menu bar or change the cursor, but other than that they’re
quite similar. A dialog has a layout manager (which defaults to
BorderLayout)
and you override
action( )
etc., or
handleEvent( )
to deal with events. One significant difference you’ll want to note in
handleEvent( ):
when the
WINDOW_DESTROY
event occurs, you don’t want to shut down the application! Instead, you
release the resources used by the dialog’s window by calling
dispose( ).

In


the following example, the dialog box is made up of a grid (using


GridLayout

)


of a special kind of button that is defined here as class


ToeButton

.


This button draws a frame around itself and, depending on its state, a blank,


an “x,” or an “o” in the middle. It starts out blank,


and then depending on whose turn it is, changes to an “x” or an


“o.” However, it will also flip back and forth between


“x” and “o” when you click on the button. (This makes


the tic-tac-toe concept only slightly more annoying than it already is.) In


addition, the dialog box can be set up for any number of rows and columns by


changing numbers in the main application window.

//: ToeTest.java
// Demonstration of dialog boxes
// and creating your own components
import java.awt.*;
 
class ToeButton extends Canvas {
  int state = ToeDialog.BLANK;
  ToeDialog parent;
  ToeButton(ToeDialog parent) {
    this.parent = parent;
  }
  public void paint(Graphics  g) {
    int x1 = 0;
    int y1 = 0;
    int x2 = size().width - 1;
    int y2 = size().height - 1;
    g.drawRect(x1, y1, x2, y2);
    x1 = x2/4;
    y1 = y2/4;
    int wide = x2/2;
    int high = y2/2;
    if(state == ToeDialog.XX) {
      g.drawLine(x1, y1, x1 + wide, y1 + high);
      g.drawLine(x1, y1 + high, x1 + wide, y1);
    }
    if(state == ToeDialog.OO) {
      g.drawOval(x1, y1, x1+wide/2, y1+high/2);
    }
  }
  public boolean
  mouseDown(Event evt, int x, int y) {
    if(state == ToeDialog.BLANK) {
      state = parent.turn;
      parent.turn= (parent.turn == ToeDialog.XX ?
        ToeDialog.OO : ToeDialog.XX);
    }
    else
      state = (state == ToeDialog.XX ?
        ToeDialog.OO : ToeDialog.XX);
    repaint();
    return true;
  }
}
 
class ToeDialog extends Dialog {
  // w = number of cells wide
  // h = number of cells high
  static final int BLANK = 0;
  static final int XX = 1;
  static final int OO = 2;
  int turn = XX; // Start with x's turn
  public ToeDialog(Frame parent, int w, int h) {
    super(parent, "The game itself", false);
    setLayout(new GridLayout(w, h));
    for(int i = 0; i < w * h; i++)
      add(new ToeButton(this));
    resize(w * 50, h * 50);
  }
  public boolean handleEvent(Event evt) {
    if(evt.id == Event.WINDOW_DESTROY)
      dispose();
    else
      return super.handleEvent(evt);
    return true;
  }
}
 
public class ToeTest extends Frame {
  TextField rows = new TextField("3");
  TextField cols = new TextField("3");
  public ToeTest() {
    setTitle("Toe Test");
    Panel p = new Panel();
    p.setLayout(new GridLayout(2,2));
    p.add(new Label("Rows", Label.CENTER));
    p.add(rows);
    p.add(new Label("Columns", Label.CENTER));
    p.add(cols);
    add("North", p);
    add("South", new Button("go"));
  }
  public boolean handleEvent(Event evt) {
    if(evt.id == Event.WINDOW_DESTROY)
      System.exit(0);
    else
      return super.handleEvent(evt);
    return true;
  }
  public boolean action(Event evt, Object arg) {
    if(arg.equals("go")) {
      Dialog d = new ToeDialog(
        this,
        Integer.parseInt(rows.getText()),
        Integer.parseInt(cols.getText()));
      d.show();
    }
    else
      return super.action(evt, arg);
    return true;
  }
  public static void main(String[] args) {
    Frame f = new ToeTest();
    f.resize(200,100);
    f.show();
  }
} ///:~ 

The


ToeButton

class keeps a handle to its parent, which must be of type


ToeDialog

.


As before, this introduces high coupling because a


ToeButton

can be used only with a


ToeDialog

,


but it solves a number of problems, and in truth it doesn’t seem like


such a bad solution because there’s no other kind of dialog that’s


keeping track of whose turn it is. Of course, you can take another approach,


which is to make


ToeDialog.turn

a


static

member of


ToeButton

.


This eliminates the coupling, but prevents you from having more than one


ToeDialog

at a time. (More than one that works properly, anyway.)

The


paint( )
method is concerned with the
graphics:
drawing the square around the button and drawing the “x” or the
“o.” This is full of tedious calculations, but it’s
straightforward.

A


mouse click is captured by the overridden

mouseDown( )
method, which first checks to see if the button has anything written on it. If
not, the parent window is queried to find out whose turn it is and that is used
to establish the state of the button. Note that the button then reaches back
into the parent and changes the turn. If the button is already displaying an
“x” or an “o” then that is flopped. You can see in
these calculations the convenient use of the ternary if-else described in
Chapter 3. After a button state change, the button is repainted.

The


constructor for


ToeDialog

is quite simple: it adds into a


GridLayout

as many buttons as you request, then resizes it for 50 pixels on a side for


each button. (If you don’t resize a


Window

,


it won’t show up!) Note that


handleEvent( )

just calls


dispose( )

for a


WINDOW_DESTROY

so the whole application doesn’t go away.

ToeTest

sets up the whole application by creating the


TextField

s


(for inputting the rows and columns of the button grid) and the


“go” button. You’ll see in


action( )

that this program uses the less-desirable “string match” technique


for detecting the button press (make sure you get spelling and capitalization


right!). When the button is pressed, the data in the


TextField

s


must be fetched, and, since they are in


String

form, turned into


int

s


using the


static
Integer.parseInt( )
method. Once the
Dialog
is created, the
show( )
method must be called to display and activate it.

You’ll


notice that the


ToeDialog

object is assigned to a


Dialog

handle


d

.


This is an example of upcasting, although it really doesn’t make much


difference here since all that’s happening is the


show( )

method is called. However, if you wanted to call some method that existed only


in


ToeDialog

you would want to assign to a


ToeDialog

handle and not lose the information in an upcast.


File
dialogs

Some


operating systems have a number of special built-in dialog boxes to handle the


selection of things such as fonts, colors, printers, and the like. Virtually


all graphical operating systems support the opening and saving of files,


however, and so Java’s

FileDialog
encapsulates these for easy use. This, of course, makes no sense at all to use
from an applet since an applet can neither read nor write files on the local
disk. (This will change for trusted applets in newer browsers.)

The


following application exercises the two forms of file dialogs, one for opening


and one for saving. Most of the code should by now be familiar, and all the


interesting activities happen in


action( )

for the two different button clicks:

//: FileDialogTest.java
// Demonstration of File dialog boxes
import java.awt.*;
 
public class FileDialogTest extends Frame {
  TextField filename = new TextField();
  TextField directory = new TextField();
  Button open = new Button("Open");
  Button save = new Button("Save");
  public FileDialogTest() {
    setTitle("File Dialog Test");
    Panel p = new Panel();
    p.setLayout(new FlowLayout());
    p.add(open);
    p.add(save);
    add("South", p);
    directory.setEditable(false);
    filename.setEditable(false);
    p = new Panel();
    p.setLayout(new GridLayout(2,1));
    p.add(filename);
    p.add(directory);
    add("North", p);
  }
  public boolean handleEvent(Event evt) {
    if(evt.id == Event.WINDOW_DESTROY)
      System.exit(0);
    else
      return super.handleEvent(evt);
    return true;
  }
  public boolean action(Event evt, Object arg) {
    if(evt.target.equals(open)) {
      // Two arguments, defaults to open file:
      FileDialog d = new FileDialog(this,
        "What file do you want to open?");
      d.setFile("*.java"); // Filename filter
      d.setDirectory("."); // Current directory
      d.show();
      String openFile;
      if((openFile = d.getFile()) != null) {
        filename.setText(openFile);
        directory.setText(d.getDirectory());
      } else {
        filename.setText("You pressed cancel");
        directory.setText("");
      }
    }
    else if(evt.target.equals(save)) {
      FileDialog d = new FileDialog(this,
        "What file do you want to save?",
        FileDialog.SAVE);
      d.setFile("*.java");
      d.setDirectory(".");
      d.show();
      String saveFile;
      if((saveFile = d.getFile()) != null) {
        filename.setText(saveFile);
        directory.setText(d.getDirectory());
      } else {
        filename.setText("You pressed cancel");
        directory.setText("");
      }
    }
    else
      return super.action(evt, arg);
    return true;
  }
  public static void main(String[] args) {
    Frame f = new FileDialogTest();
    f.resize(250,110);
    f.show();
  }
} ///:~ 

For


an “open file” dialog, you use the constructor that takes two


arguments; the first is the parent window handle and the second is the title


for the title bar of the


FileDialog

.


The method

setFile( )
provides an initial file name – presumably the native OS supports
wildcards, so in this example all the
.java
files will initially be displayed. The
setDirectory( )
method chooses the directory where the file selection will begin. (In general,
the OS allows the user to change directories.)

The


show( )
command doesn’t return until the dialog is closed. The
FileDialog
object still exists, so you can read data from it. If you call
getFile( )
and it returns
null
it means the user canceled out of the dialog. Both the file name and the
results of
getDirectory( )
are displayed in the
TextFields.

The


button for saving works the same way, except that it uses a different


constructor for the


FileDialog

.


This constructor takes three arguments and the third argument must be either


FileDialog.SAVE

or


FileDialog.OPEN

.

Contents

|

Prev

|

Next
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.