Monday 27 March 2017

Menu Bars and Menus - Java Tutorials

A top-level window can have a menu bar associated with it. A menu bar displays a list of top-level menu choices. Each choice is associated with a drop-down menu. This concept is implemented in Java by the following classes: MenuBar, Menu, and MenuItem. In general, a menu bar contains one or more Menu objects. Each Menu object contains a list of MenuItem objects. Each MenuItem object represents something that can be selected by the user. Since Menu is a subclass of MenuItem, a hierarchy of nested submenus can be created. It is also possible to include checkable menu items. These are menu options of type CheckboxMenuItem and will have a check mark next to them when they are selected.

To create a menu bar, first create an instance of MenuBar. This class only defines the default constructor. Next, create instances of Menu that will define the selections displayed on the bar. Following are the constructors for Menu:

      Menu( )
      Menu(String optionName)
      Menu(String optionName, boolean removable)

Here, optionName specifies the name of the menu selection. If removable is true, the pop-up menu can be removed and allowed to float free. Otherwise, it will remain attached to the menu bar. (Removable menus are implementation-dependent.) The first form creates an empty menu. Individual menu items are of type MenuItem. It defines these constructors:

      MenuItem( )
      MenuItem(String itemName)
      MenuItem(String itemName, MenuShortcut keyAccel)

Here, itemName is the name shown in the menu, and keyAccel is the menu shortcut for this item. You can disable or enable a menu item by using the setEnabled( ) method. Its form is shown here:

      void setEnabled(boolean enabledFlag)

If the argument enabledFlag is true, the menu item is enabled. If false, the menu item is disabled. You can determine an item’s status by calling isEnabled( ). This method is shown here:

      boolean isEnabled( )

isEnabled( ) returns true if the menu item on which it is called is enabled. Otherwise, it returns false. You can change the name of a menu item by calling setLabel( ). You can retrieve the current name by using getLabel( ). These methods are as follows:

      void setLabel(String newName)
      String getLabel( )

Here, newName becomes the new name of the invoking menu item. getLabel( ) returns the current name. You can create a checkable menu item by using a subclass of MenuItem called CheckboxMenuItem. It has these constructors:

      CheckboxMenuItem( )
      CheckboxMenuItem(String itemName)
      CheckboxMenuItem(String itemName, boolean on)

Here, itemName is the name shown in the menu. Checkable items operate as toggles. Each time one is selected, its state changes. In the first two forms, the checkable entry is unchecked. In the third form, if on is true, the checkable entry is initially checked. Otherwise, it is cleared. You can obtain the status of a checkable item by calling getState( ). You can set it to a known state by using setState( ). These methods are shown here:

      boolean getState( )
      void setState(boolean checked)

If the item is checked, getState( ) returns true. Otherwise, it returns false. To check an item, pass true to setState( ). To clear an item, pass false. Once you have created a menu item, you must add the item to a Menu object by using add( ), which has the following general form:

      MenuItem add(MenuItem item)

Here, item is the item being added. Items are added to a menu in the order in which the calls to add( ) take place. The item is returned. Once you have added all items to a Menu object, you can add that object to the menu bar by using this version of add( ) defined by MenuBar:

      Menu add(Menu menu)

Here, menu is the menu being added. The menu is returned.

Menus only generate events when an item of type MenuItem or CheckboxMenuItem is selected. They do not generate events when a menu bar is accessed to display a drop-down menu, for example. Each time a menu item is selected, an ActionEvent object is generated. Each time a check box menu item is checked or unchecked, an ItemEvent object is generated. Thus, you must implement the ActionListener and ItemListener interfaces in order to handle these menu events. The getItem( ) method of ItemEvent returns a reference to the item that generated this event. The general form of this method is shown here:

      Object getItem( )

Following is an example that adds a series of nested menus to a pop-up window. The item selected is displayed in the window. The state of the two check box menu items is also displayed.

  // Illustrate menus.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="MenuDemo" width=250 height=250>
    </applet>
  */

  // Create a subclass of Frame
  class MenuFrame extends Frame {
    String msg = "";
    CheckboxMenuItem debug, test;

    MenuFrame(String title) {
      super(title);

      // create menu bar and add it to frame
      MenuBar mbar = new MenuBar();
      setMenuBar(mbar);

      // create the menu items
      Menu file = new Menu("File");
      MenuItem item1, item2, item3, item4, item5;
      file.add(item1 = new MenuItem("New..."));
      file.add(item2 = new MenuItem("Open..."));
      file.add(item3 = new MenuItem("Close"));
      file.add(item4 = new MenuItem("-"));
      file.add(item5 = new MenuItem("Quit..."));
      mbar.add(file);

      Menu edit = new Menu("Edit");
      MenuItem item6, item7, item8, item9;
      edit.add(item6 = new MenuItem("Cut"));
      edit.add(item7 = new MenuItem("Copy"));
      edit.add(item8 = new MenuItem("Paste"));
      edit.add(item9 = new MenuItem("-"));
      Menu sub = new Menu("Special");
      MenuItem item10, item11, item12;
      sub.add(item10 = new MenuItem("First"));
      sub.add(item11 = new MenuItem("Second"));
      sub.add(item12 = new MenuItem("Third"));
      edit.add(sub);

      // these are checkable menu items
      debug = new CheckboxMenuItem("Debug");
      edit.add(debug);
      test = new CheckboxMenuItem("Testing");
      edit.add(test);

      mbar.add(edit);

      // create an object to handle action and item events
      MyMenuHandler handler = new MyMenuHandler(this);
      // register it to receive those events
      item1.addActionListener(handler);
      item2.addActionListener(handler);
      item3.addActionListener(handler);
      item4.addActionListener(handler);
      item5.addActionListener(handler);
      item6.addActionListener(handler);
      item7.addActionListener(handler);
      item8.addActionListener(handler);
      item9.addActionListener(handler);
      item10.addActionListener(handler);
      item11.addActionListener(handler);
      item12.addActionListener(handler);
      debug.addItemListener(handler);
      test.addItemListener(handler);

      // create an object to handle window events
      MyWindowAdapter adapter = new MyWindowAdapter(this);
        // register it to receive those events
      addWindowListener(adapter);
    }

    public void paint(Graphics g) {
      g.drawString(msg, 10, 200);

      if(debug.getState())
         g.drawString("Debug is on.", 10, 220);
      else
         g.drawString("Debug is off.", 10, 220);

      if(test.getState())
         g.drawString("Testing is on.", 10, 240);
      else
         g.drawString("Testing is off.", 10, 240);
    }
  }

  class MyWindowAdapter extends WindowAdapter {
    MenuFrame menuFrame;
    public MyWindowAdapter(MenuFrame menuFrame) {
      this.menuFrame = menuFrame;
    }
    public void windowClosing(WindowEvent we) {
      menuFrame.setVisible(false);
    }
  }

  class MyMenuHandler implements ActionListener, ItemListener {
    MenuFrame menuFrame;
    public MyMenuHandler(MenuFrame menuFrame) {
      this.menuFrame = menuFrame;
    }
    // Handle action events
    public void actionPerformed(ActionEvent ae) {
        String msg = "You selected ";
        String arg = (String)ae.getActionCommand();
        if(arg.equals("New..."))
          msg += "New.";
        else if(arg.equals("Open..."))
          msg += "Open.";
        else if(arg.equals("Close"))
          msg += "Close.";
        else if(arg.equals("Quit..."))
          msg += "Quit.";
        else if(arg.equals("Edit"))
          msg += "Edit.";
        else if(arg.equals("Cut"))
          msg += "Cut.";
        else if(arg.equals("Copy"))
          msg += "Copy.";
        else if(arg.equals("Paste"))
          msg += "Paste.";
        else if(arg.equals("First"))
          msg += "First.";
        else if(arg.equals("Second"))
          msg += "Second.";
        else if(arg.equals("Third"))
          msg += "Third.";
        else if(arg.equals("Debug"))
          msg += "Debug.";
        else if(arg.equals("Testing"))
          msg += "Testing.";
        menuFrame.msg = msg;
        menuFrame.repaint();
    }
    // Handle item events
    public void itemStateChanged(ItemEvent ie) {
      menuFrame.repaint();
    }
  }
  
  // Create frame window.
  public class MenuDemo extends Applet {
    Frame f;

    public void init() {
      f = new MenuFrame("Menu Demo");
      int width = Integer.parseInt(getParameter("width"));
      int height = Integer.parseInt(getParameter("height"));
   
      setSize(new Dimension(width, height));
      
      f.setSize(width, height);
      f.setVisible(true);
    }

    public void start() {
      f.setVisible(true);
    }

    public void stop() {
      f.setVisible(false);
    }
  }

There is one other menu-related class that you might find interesting: PopupMenu. It works just like Menu but produces a menu that can be displayed at a specific location. PopupMenu provides a flexible, useful alternative for some types of menuing situations.

Understanding Layout Managers - Java Tutorials

All of the components that we have shown so far have been positioned by the default layout manager. As we mentioned at the beginning of this chapter, a layout manager automatically arranges your controls within a window by using some type of algorithm. If you have programmed for other GUI environments, such as Windows, then you are accustomed to laying out your controls by hand. While it is possible to lay out Java controls by hand, too, you generally won’t want to, for two main reasons. First, it is very tedious to manually lay out a large number of components. Second, sometimes the width and height information is not yet available when you need to arrange some control, because the native toolkit components haven’t been realized. This is a chicken-and-egg situation; it is pretty confusing to figure out when it is okay to use the size of a given component to position it relative to another.

Each Container object has a layout manager associated with it. A layout manager is an instance of any class that implements the LayoutManager interface. The layout manager is set by the setLayout( ) method. If no call to setLayout( ) is made, then the default layout manager is used. Whenever a container is resized (or sized for the first time), the layout manager is used to position each of the components within it. The setLayout( ) method has the following general form:

      void setLayout(LayoutManager layoutObj)

Here, layoutObj is a reference to the desired layout manager. If you wish to disable the layout manager and position components manually, pass null for layoutObj. If you do this, you will need to determine the shape and position of each component manually, using the setBounds( ) method defined by Component. Normally, you will want to use a layout manager.

Each layout manager keeps track of a list of components that are stored by their names. The layout manager is notified each time you add a component to a container. Whenever the container needs to be resized, the layout manager is consulted via its minimumLayoutSize( ) and preferredLayoutSize( ) methods.  Each component  that is being managed by a layout  manager contains the getPreferredSize ( ) and getMinimumSize( ) methods. These return the preferred and minimum size required to display each component. The layout manager will honor these requests if at all possible, while maintaining the integrity of the layout policy. You may override these methods for controls that you subclass. Default values are provided otherwise. Java has several predefined LayoutManager classes, several of which are described next. You can use the layout manager that best fits your application.


FlowLayout

FlowLayout is the default layout manager. This is the layout manager that the preceding examples have used. FlowLayout implements a simple layout style, which is similar to how words flow in a text editor. Components are laid out from the upper-left corner, left to right and top to bottom. When no more components fit on a line, the next one appears on the next line. A small space is left between each component, above and below, as well as left and right. Here are the constructors for FlowLayout:

      FlowLayout( )
      FlowLayout(int how)
      FlowLayout(int how, int horz, int vert)

The first form creates the default layout, which centers components and leaves five pixels of space between each component. The second form lets you specify how each line is aligned. Valid values for how are as follows:

      FlowLayout.LEFT
      FlowLayout.CENTER
      FlowLayout.RIGHT

These values specify left, center, and right alignment, respectively. The third form allows you to specify the horizontal and vertical space left between components in horz and vert, respectively.

Here is a version of the CheckboxDemo applet shown earlier in this chapter, modified so that it uses left-aligned flow layout.

  // Use left-aligned flow layout.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="FlowLayoutDemo" width=250 height=200>
    </applet>
  */

  public class FlowLayoutDemo extends Applet
    implements ItemListener {

    String msg = "";
    Checkbox Win98, winNT, solaris, mac;

    public void init() {
      // set left-aligned flow layout
      setLayout(new FlowLayout(FlowLayout.LEFT));

      Win98 = new Checkbox("Windows 98/XP", null, true);
      winNT = new Checkbox("Windows NT/2000");
      solaris = new Checkbox("Solaris");
      mac = new Checkbox("MacOS");

      add(Win98);
      add(winNT);
      add(solaris);
      add(mac);

      // register to receive item events
      Win98.addItemListener(this);
      winNT.addItemListener(this);
      solaris.addItemListener(this);
      mac.addItemListener(this);
    }

    // Repaint when status of a check box changes.
    public void itemStateChanged(ItemEvent ie) {
      repaint();
    }

    // Display current state of the check boxes.
    public void paint(Graphics g) {
      msg = "Current state: ";
      g.drawString(msg, 6, 80);
      msg = " Windows 98/XP: " + Win98.getState();
      g.drawString(msg, 6, 100);
      msg = " Windows NT/2000: " + winNT.getState();
      g.drawString(msg, 6, 120);
      msg = " Solaris: " + solaris.getState();
      g.drawString(msg, 6, 140);
      msg = " Mac: " + mac.getState();
      g.drawString(msg, 6, 160);
    }
  }


BorderLayout

The BorderLayout class implements a common layout style for top-level windows. It has four narrow, fixed-width components at the edges and one large area in the center. The four sides are referred to as north, south, east, and west. The middle area is called the center. Here are the constructors defined by BorderLayout:

      BorderLayout( )
      BorderLayout(int horz, int vert)

The first form creates a default border layout. The second allows you to specify the horizontal and vertical space left between components in horz and vert, respectively. BorderLayout defines the following constants that specify the regions:

      BorderLayout.CENTER 
      BorderLayout.SOUTH
      BorderLayout.EAST 
      BorderLayout.WEST
      BorderLayout.NORTH

When adding components, you will use these constants with the following form of add( ), which is defined by Container:

      void add(Component compObj, Object region);

Here, compObj is the component to be added, and region specifies where the component will be added. Here is an example of a BorderLayout with a component in each layout area:

  // Demonstrate BorderLayout.
  import java.awt.*;
  import java.applet.*;
  import java.util.*;
  /*
  <applet code="BorderLayoutDemo" width=400 height=200>
  </applet>
  */

  public class BorderLayoutDemo extends Applet {
    public void init() {
      setLayout(new BorderLayout());

      add(new Button("This is across the top."),
          BorderLayout.NORTH);
      add(new Label("The footer message might go here."),
          BorderLayout.SOUTH);
      add(new Button("Right"), BorderLayout.EAST);
      add(new Button("Left"), BorderLayout.WEST);

      String msg = "The reasonable man adapts " +
        "himself to the world;\n" +
        "the unreasonable one persists in " +
        "trying to adapt the world to himself.\n" +
        "Therefore all progress depends " +
        "on the unreasonable man.\n\n" +
        "         - George Bernard Shaw\n\n";

      add(new TextArea(msg), BorderLayout.CENTER);
    }
  }


Using Insets

Sometimes you will want to leave a small amount of space between the container that holds your components and the window that contains it. To do this, override the getInsets( ) method that is defined by Container. This function returns an Insets object that contains the top, bottom, left, and right inset to be used when the container is displayed. These values are used by the layout manager to inset the components when it lays out the window. The constructor for Insets is shown here:

      Insets(int top, int left, int bottom, int right)

The values passed in top, left, bottom, and right specify the amount of space between the container and its enclosing window. The getInsets( ) method has this general form:

      Insets getInsets( )

When overriding one of these methods, you must return a new Insets object that contains the inset spacing you desire. Here is the preceding BorderLayout example modified so that it insets its components ten pixels from each border. The background color has been set to cyan to help make the insets more visible.

  // Demonstrate BorderLayout with insets.
  import java.awt.*;
  import java.applet.*;
  import java.util.*;
  /*
  <applet code="InsetsDemo" width=400 height=200>
  </applet>
  */

  public class InsetsDemo extends Applet {
    public void init() {
      // set background color so insets can be easily seen
      setBackground(Color.cyan);

      setLayout(new BorderLayout());

      add(new Button("This is across the top."),
          BorderLayout.NORTH);
      add(new Label("The footer message might go here."),
          BorderLayout.SOUTH);
      add(new Button("Right"), BorderLayout.EAST);
      add(new Button("Left"), BorderLayout.WEST);

      String msg = "The reasonable man adapts " +
        "himself to the world;\n" +
        "the unreasonable one persists in " +
        "trying to adapt the world to himself.\n" +
        "Therefore all progress depends " +
        "on the unreasonable man.\n\n" +
        "         - George Bernard Shaw\n\n";

      add(new TextArea(msg), BorderLayout.CENTER);
    }
    // add insets
    public Insets getInsets() {
      return new Insets(10, 10, 10, 10);
    }
  }


GridLayout

GridLayout lays out components in a two-dimensional grid. When you instantiate a GridLayout, you define the number of rows and columns. The constructors supported by GridLayout are shown here:

      GridLayout( )
      GridLayout(int numRows, int numColumns )
      GridLayout(int numRows, int numColumns, int horz, int vert)

The first form creates a single-column grid layout. The second form creates a grid layout with the specified number of rows and columns. The third form allows you to specify the horizontal and vertical space left between components in horz and vert, respectively. Either numRows or numColumns can be zero. Specifying numRows as zero allows for unlimited-length columns. Specifying numColumns as zero allows for unlimited-length rows. Here is a sample program that creates a 4×4 grid and fills it in with 15 buttons, each labeled with its index:

  // Demonstrate GridLayout
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="GridLayoutDemo" width=300 height=200>
  </applet>
  */

  public class GridLayoutDemo extends Applet {
    static final int n = 4;
    public void init() {
      setLayout(new GridLayout(n, n));

      setFont(new Font("SansSerif", Font.BOLD, 24));

      for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
          int k = i * n + j;
          if(k > 0)
            add(new Button("" + k));
        }
      }
    }
  }

You might try using this example as the starting point for a 15-square puzzle.


CardLayout

The CardLayout class is unique among the other layout managers in that it stores several different layouts. Each layout can be thought of as being on a separate index card in a deck that can be shuffled so that any card is on top at a given time. This can be useful for user interfaces with optional components that can be dynamically enabled and disabled upon user input. You can prepare the other layouts and have them hidden, ready to be activated when needed. CardLayout provides these two constructors:

      CardLayout( )
      CardLayout(int horz, int vert)

The first form creates a default card layout. The second form allows you to specify the horizontal and vertical space left between components in horz and vert, respectively. Use of a card layout requires a bit more work than the other layouts. The cards are typically held in an object of type Panel. This panel must have CardLayout selected as its layout manager. The cards that form the deck are also typically objects of type Panel. Thus, you must create a panel that contains the deck and a panel for each card in the deck. Next, you add to the appropriate panel the components that form each card. You then add these panels to the panel for which CardLayout is the layout manager. Finally, you add this panel to the main applet panel. Once these steps are complete, you must provide some way for the user to select between cards. One common approach is to include one push button for each card in the deck.

When card panels are added to a panel, they are usually given a name. Thus, most of the time, you will use this form of add( ) when adding cards to a panel:

      void add(Component panelObj, Object name);

Here, name is a string that specifies the name of the card whose panel is specified by panelObj. After you have created a deck, your program activates a card by calling one of the following methods defined by CardLayout:

      void first(Container deck)
      void last(Container deck)
      void next(Container deck)
      void previous(Container deck)
      void show(Container deck, String cardName)

Here, deck is a reference to the container (usually a panel) that holds the cards, and cardName is the name of a card. Calling first( ) causes the first card in the deck to be shown. To show the last card, call last( ). To show the next card, call next( ). To show the previous card, call previous( ). Both next( ) and previous( ) automatically cycle back to the top or bottom of the deck, respectively. The show( ) method displays the card whose name is passed in cardName.

The following example creates a two-level card deck that allows the user to select an operating system. Windows-based operating systems are displayed in one card. Macintosh and Solaris are displayed in the other card.

  // Demonstrate CardLayout.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="CardLayoutDemo" width=300 height=100>
    </applet>
  */

  public class CardLayoutDemo extends Applet
    implements ActionListener, MouseListener {

    Checkbox Win98, winNT, solaris, mac;
    Panel osCards;
    CardLayout cardLO;
    Button Win, Other;

    public void init() {
      Win = new Button("Windows");
      Other = new Button("Other");
      add(Win);
      add(Other);

      cardLO = new CardLayout();
      osCards = new Panel();
      osCards.setLayout(cardLO); // set panel layout to card layout

      Win98 = new Checkbox("Windows 98/XP", null, true);
      winNT = new Checkbox("Windows NT/2000");
      solaris = new Checkbox("Solaris");
      mac = new Checkbox("MacOS");

      // add Windows check boxes to a panel
      Panel winPan = new Panel();
      winPan.add(Win98);
      winPan.add(winNT);

      // Add other OS check boxes to a panel
      Panel otherPan = new Panel();
      otherPan.add(solaris);
      otherPan.add(mac);

      // add panels to card deck panel
      osCards.add(winPan, "Windows");
      osCards.add(otherPan, "Other");

      // add cards to main applet panel
      add(osCards);

      // register to receive action events
      Win.addActionListener(this);
      Other.addActionListener(this);

      // register mouse events
      addMouseListener(this);
    }

    // Cycle through panels.
    public void mousePressed(MouseEvent me) {
      cardLO.next(osCards);
    }

    // Provide empty implementations for the other 
                                     MouseListener methods.
    public void mouseClicked(MouseEvent me) {
    }
    public void mouseEntered(MouseEvent me) {
    }
    public void mouseExited(MouseEvent me) {
    }
    public void mouseReleased(MouseEvent me) {
    }
    
    public void actionPerformed(ActionEvent ae) {
      if(ae.getSource() == Win) {
        cardLO.show(osCards, "Windows");
      }
      else {
        cardLO.show(osCards, "Other");
      }
    }
  }

Using Lists, Managing Scroll Bars, Using a TextField & Using a TextArea - Java Tutorials

Using Lists

The List class provides a compact, multiple-choice, scrolling selection list. Unlike the Choice object, which shows only the single selected item in the menu, a List object can be constructed to show any number of choices in the visible window. It can also be created to allow multiple selections. List provides these constructors:

      List( )
      List(int numRows)
      List(int numRows, boolean multipleSelect)

The first version creates a List control that allows only one item to be selected at any one time. In the second form, the value of numRows specifies the number of entries in the list that will always be visible (others can be scrolled into view as needed). In the third form, if multipleSelect is true, then the user may select two or more items at a time. If it is false, then only one item may be selected. To add a selection to the list, call add( ). It has the following two forms:

      void add(String name)
      void add(String name, int index)

Here, name is the name of the item added to the list. The first form adds items to the end of the list. The second form adds the item at the index specified by index. Indexing begins at zero. You can specify –1 to add the item to the end of the list. For lists that allow only single selection, you can determine which item is currently selected by calling either getSelectedItem( ) or getSelectedIndex( ). These methods are shown here:

      String getSelectedItem( )
      int getSelectedIndex( )

The getSelectedItem( ) method returns a string containing the name of the item. If more than one item is selected or if no selection has yet been made, null is returned. getSelectedIndex( ) returns the index of the item. The first item is at index 0. If more than one item is selected, or if no selection has yet been made, –1 is returned. For lists that allow multiple selection, you must use either getSelectedItems( ) or getSelectedIndexes( ), shown here, to determine the current selections:

      String[ ] getSelectedItems( )
      int[ ] getSelectedIndexes( )

getSelectedItems( ) returns an array containing the names of the currently selected items. getSelectedIndexes( ) returns an array containing the indexes of the currently selected items. To obtain the number of items in the list, call getItemCount( ). You can set the currently selected item by using the select( ) method with a zero-based integer index. These methods are shown here:

      int getItemCount( )
      void select(int index)

Given an index, you can obtain the name associated with the item at that index by calling getItem( ), which has this general form:

      String getItem(int index)

Here, index specifies the index of the desired item.


Handling Lists

To process list events, you will need to implement the ActionListener interface. Each time a List item is double-clicked, an ActionEvent object is generated. Its getActionCommand( ) method can be used to retrieve the name of the newly selected item. Also, each time an item is selected or deselected with a single click, an ItemEvent object is generated. Its getStateChange( ) method can be used to determine whether a selection or deselection triggered this event. getItemSelectable( ) returns a reference to the object that triggered this event.

Here is an example that converts the Choice controls in the preceding section into List components, one multiple choice and the other single choice:

  // Demonstrate Lists.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="ListDemo" width=300 height=180>
    </applet>
  */

  public class ListDemo extends Applet implements ActionListener {
    List os, browser;
    String msg = "";

    public void init() {
    os = new List(4, true);
    browser = new List(4, false);

    // add items to os list
      os.add("Windows 98/XP");
      os.add("Windows NT/2000");
      os.add("Solaris");
      os.add("MacOS");

      // add items to browser list
      browser.add("Netscape 3.x");
      browser.add("Netscape 4.x");
      browser.add("Netscape 5.x");
      browser.add("Netscape 6.x");

      browser.add("Internet Explorer 4.0");
      browser.add("Internet Explorer 5.0");
      browser.add("Internet Explorer 6.0");

      browser.add("Lynx 2.4");
  
      browser.select(1);

      // add lists to window
      add(os);
      add(browser);

      // register to receive action events
      os.addActionListener(this);
      browser.addActionListener(this);
    }

    public void actionPerformed(ActionEvent ae) {
      repaint();
    }

    // Display current selections.
    public void paint(Graphics g) {
      int idx[];

      msg = "Current OS: ";
      idx = os.getSelectedIndexes();
      for(int i=0; i<idx.length; i++)
        msg += os.getItem(idx[i]) + " ";
      g.drawString(msg, 6, 120);
      msg = "Current Browser: ";
      msg += browser.getSelectedItem();
      g.drawString(msg, 6, 140);
    }
  }




Managing Scroll Bars

Scroll bars are used to select continuous values between a specified minimum and maximum. Scroll bars may be oriented horizontally or vertically. A scroll bar is actually a composite of several individual parts. Each end has an arrow that you can click to move the current value of the scroll bar one unit in the direction of the arrow. The current value of the scroll bar relative to its minimum and maximum values is indicated by the slider box (or thumb) for the scroll bar. The slider box can be dragged by the user to a new position. The scroll bar will then reflect this value. In the background space on either side of the thumb, the user can click to cause the thumb to jump in that direction by some increment larger than 1. Typically, this action translates into some form of page up and page down. Scroll bars are encapsulated by the Scrollbar class.

Scrollbar defines the following constructors:

      Scrollbar( )
      Scrollbar(int style)
      Scrollbar(int style, int initialValue, int thumbSize, int min, int max)

The first form creates a vertical scroll bar. The second and third forms allow you to specify the orientation of the scroll bar. If style is Scrollbar.VERTICAL, a vertical scroll bar is created. If style is Scrollbar.HORIZONTAL, the scroll bar is horizontal. In the third form of the constructor, the initial value of the scroll bar is passed in initialValue. The number of units represented by the height of the thumb is passed in thumbSize. The minimum and maximum values for the scroll bar are specified by min and max. If you construct a scroll bar by using one of the first two constructors, then you need to set its parameters by using setValues( ), shown here, before it can be used: 

      void setValues(int initialValue, int thumbSize, int min, int max)

The parameters have the same meaning as they have in the third constructor just described. To obtain the current value of the scroll bar, call getValue( ). It returns the current setting. To set the current value, call setValue( ). These methods are as follows:

      int getValue( )
      void setValue(int newValue)

Here, newValue specifies the new value for the scroll bar. When you set a value, the slider box inside the scroll bar will be positioned to reflect the new value. You can also retrieve the minimum and maximum values via getMinimum( ) and getMaximum( ), shown here:

      int getMinimum( )
      int getMaximum( )

They return the requested quantity. By default, 1 is the increment added to or subtracted from the scroll bar each time it is scrolled up or down one line. You can change this increment by calling setUnitIncrement( ). By default, page-up and page-down increments are 10. You can change this value by calling setBlockIncrement( ). These methods are shown here:

      void setUnitIncrement(int newIncr)
      void setBlockIncrement(int newIncr)


Handling Scroll Bars

To process scroll bar events, you need to implement the AdjustmentListener interface. Each time a user interacts with a scroll bar, an AdjustmentEvent object is generated. Its getAdjustmentType( ) method can be used to determine the type of the adjustment. The types of adjustment events are as follows:

BLOCK_DECREMENT:  A page-down event has been generated.

BLOCK_INCREMENT:  A page-up event has been generated.

TRACK:  An absolute tracking event has been generated.

UNIT_DECREMENT:  The line-down button in a scroll bar has been pressed.

UNIT_INCREMENT:  The line-up button in a scroll bar has been pressed.

The following example creates both a vertical and a horizontal scroll bar. The current settings of the scroll bars are displayed. If you drag the mouse while inside the window, the coordinates of each drag event are used to update the scroll bars. An asterisk is displayed at the current drag position.

  // Demonstrate scroll bars.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="SBDemo" width=300 height=200>
    </applet>
  */

  public class SBDemo extends Applet
    implements AdjustmentListener, MouseMotionListener {
    String msg = "";
    Scrollbar vertSB, horzSB;

    public void init() {
      int width = Integer.parseInt(getParameter("width"));
      int height = Integer.parseInt(getParameter("height"));

      vertSB = new Scrollbar(Scrollbar.VERTICAL,
                             0, 1, 0, height);
      horzSB = new Scrollbar(Scrollbar.HORIZONTAL,
                             0, 1, 0, width);
      add(vertSB);
      add(horzSB);

      // register to receive adjustment events
      vertSB.addAdjustmentListener(this);
      horzSB.addAdjustmentListener(this);

      addMouseMotionListener(this);
    }

    public void adjustmentValueChanged(AdjustmentEvent ae) {
      repaint();
    }

    // Update scroll bars to reflect mouse dragging.
    public void mouseDragged(MouseEvent me) {
      int x = me.getX();
      int y = me.getY();
      vertSB.setValue(y);
      horzSB.setValue(x);
      repaint();
    }

    // Necessary for MouseMotionListener
    public void mouseMoved(MouseEvent me) {
    }

    // Display current value of scroll bars.
    public void paint(Graphics g) {
      msg = "Vertical: " + vertSB.getValue();
      msg += ", Horizontal: " + horzSB.getValue();
      g.drawString(msg, 6, 160);

      // show current mouse drag position
      g.drawString("*", horzSB.getValue(),
                   vertSB.getValue());
    }
  }




Using a TextField

The TextField class implements a single-line text-entry area, usually called an edit control. Text fields allow the user to enter strings and to edit the text using the arrow keys, cut and paste keys, and mouse selections. TextField is a subclass of TextComponent. TextField defines the following constructors:

      TextField( )
      TextField(int numChars)
      TextField(String str)
      TextField(String str, int numChars)

The first version creates a default text field. The second form creates a text field that is numChars characters wide. The third form initializes the text field with the string contained in str. The fourth form initializes a text field and sets its width. TextField (and its superclass TextComponent) provides several methods that allow you to utilize a text field. To obtain the string currently contained in the text field, call getText( ). To set the text, call setText( ). These methods are as follows:

      String getText( )
      void setText(String str)

Here, str is the new string. The user can select a portion of the text in a text field. Also, you can select a portion of text under program control by using select( ). Your program can obtain the currently selected text by calling getSelectedText( ). These methods are shown here:

      String getSelectedText( )
      void select(int startIndex, int endIndex)

getSelectedText( ) returns the selected text. The select( ) method selects the characters beginning at startIndex and ending at endIndex–1. You can control whether the contents of a text field may be modified by the user by calling setEditable( ). You can determine editability by calling isEditable( ). These methods are shown here:

      boolean isEditable( )
      void setEditable(boolean canEdit)

isEditable( ) returns true if the text may be changed and false if not. In setEditable( ), if canEdit is true, the text may be changed. If it is false, the text cannot be altered. There may be times when you will want the user to enter text that is not displayed, such as a password. You can disable the echoing of the characters as they are typed by calling setEchoChar( ). This method specifies a single character that the TextField will display when characters are entered (thus, the actual characters typed will not be shown). You can check a text field to see if it is in this mode with the echoCharIsSet( ) method. You can retrieve the echo character by calling the getEchoChar( ) method. These methods are as follows:

      void setEchoChar(char ch)
      boolean echoCharIsSet( )
      char getEchoChar( )

Here, ch specifies the character to be echoed.


Handling a TextField

Since text fields perform their own editing functions, your program generally will not respond to individual key events that occur within a text field. However, you may want to respond when the user presses ENTER. When this occurs, an action event is generated. Here is an example that creates the classic user name and password screen:

  // Demonstrate text field.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="TextFieldDemo" width=380 height=150>
    </applet>
  */

  public class TextFieldDemo extends Applet
    implements ActionListener {

    TextField name, pass;

    public void init() {
      Label namep = new Label("Name: ", Label.RIGHT);
      Label passp = new Label("Password: ", Label.RIGHT);
      name = new TextField(12);
      pass = new TextField(8);
      pass.setEchoChar('?');

      add(namep);
      add(name);
      add(passp);
      add(pass);

      // register to receive action events
      name.addActionListener(this);
      pass.addActionListener(this);
    }

    // User pressed Enter.
    public void actionPerformed(ActionEvent ae) {
      repaint();
    }

    public void paint(Graphics g) {
      g.drawString("Name: " + name.getText(), 6, 60);
      g.drawString("Selected text in name: "
                   + name.getSelectedText(), 6, 80);
      g.drawString("Password: " + pass.getText(), 6, 100);
    }
  }




Using a TextArea

Sometimes a single line of text input is not enough for a given task. To handle these situations, the AWT includes a simple multiline editor called TextArea. Following are the constructors for TextArea:

      TextArea( )
      TextArea(int numLines, int numChars)
      TextArea(String str)
      TextArea(String str, int numLines, int numChars)
      TextArea(String str, int numLines, int numChars, int sBars)

Here, numLines specifies the height, in lines, of the text area, and numChars specifies its width, in characters. Initial text can be specified by str. In the fifth form you can specify the scroll bars that you want the control to have. sBars must be one of these values:

      SCROLLBARS_BOTH 
      SCROLLBARS_NONE
      SCROLLBARS_HORIZONTAL_ONLY 
      SCROLLBARS_VERTICAL_ONLY

TextArea is a subclass of TextComponent. Therefore, it supports the getText( ), setText( ), getSelectedText( ), select( ), isEditable( ), and setEditable( ) methods described in the preceding section.

TextArea adds the following methods:

      void append(String str)
      void insert(String str, int index)
      void replaceRange(String str, int startIndex, int endIndex)

The append( ) method appends the string specified by str to the end of the current text. insert( ) inserts the string passed in str at the specified index. To replace text, call replaceRange( ). It replaces the characters from startIndex to endIndex–1, with the replacement text passed in str.

Text areas are almost self-contained controls. Your program incurs virtually no management overhead. Text areas only generate got-focus and lost-focus events. Normally, your program simply obtains the current text when it is needed. The following program creates a TextArea control:

  // Demonstrate TextArea.
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="TextAreaDemo" width=300 height=250>
  </applet>
  */

  public class TextAreaDemo extends Applet {
    public void init() {
      String val = "There are two ways of constructing " +
        "a software design.\n" +
        "One way is to make it so simple\n" +
        "that there are obviously no deficiencies.\n" +
        "And the other way is to make it so complicated\n" +
        "that there are no obvious deficiencies.\n\n" +
        "         -C.A.R. Hoare\n\n" +
        "There's an old story about the person who wished\n" +
        "his computer were as easy to use as his telephone.\n" +
        "That wish has come true,\n" +
        "since I no longer know how to use my telephone.\n\n" +
        "         -Bjarne Stroustrup, AT&T, (inventor of C++)";

      TextArea text = new TextArea(val, 10, 30);
      add(text);
    }

  }