Page: (Bot) (Prev) (Next) Class: (Outline) (Summary) (Assign) (Answer) Course: (Cover) (Content) (Glossary)
IT508 - INTERNET PROGRAMMING - CLASS 7
ANSWERS

To: (Problems)

PROBLEMS (Top)

  1. The spreadsheet example used a GridLayout. Would there be any advantage in using a GridBagLayout to construct the spreadsheet?

    One advantage would be to weight the column and row labels so that they remain fixed in size.

  2. Outline code for a BorderPanel class that uses a GridBagLayout to emulate a BorderLayout. Creating this class is a useful academic exercise. How might this class also be useful in the real world?

    The code for the BorderPanel which is a new type of Container is:

      import java.awt.*;
    

    class BorderPanel extends Container { private GridBagLayout grid; private GridBagConstraints gbc;

    //Constructor

    public BorderPanel() { super(); //Create grid layout grid = new GridBagLayout(); gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; //Set panel layout to grid this.setLayout(grid); }

    //Helper method to set constraints and add component

    private void addComponent(Component comp, int xLoc, int yLoc, int width, int height, double xWeight, double yWeight) { //Set constraints gbc.gridx = xLoc; gbc.gridy = yLoc; gbc.gridwidth = width; gbc.gridheight = height; gbc.weightx = xWeight; gbc.weighty = yWeight; grid.setConstraints(comp,gbc); //Add component to container super.add(comp); }

    //Override add method

    public Component add(String locate, Component comp) { if (locate.equals("North")) addComponent(comp,0,0,3,1,1.0,0.0); else if (locate.equals("West")) addComponent(comp,0,1,1,1,0.0,1.0); else if (locate.equals("East")) addComponent(comp,2,1,1,1,0.0,1.0); else if (locate.equals("South")) addComponent(comp,0,2,3,1,1.0,0.0); else if (locate.equals("Center")) addComponent(comp,1,1,1,1,1.0,1.0); else throw new RuntimeException ("BorderPanel Location Error " + locate); return(comp); } }

    Basically, the add method assumes a 3 x 3 grid and places the components in the grid. It assigns appropriate weights so that the center will get all of the increased size in both directions with the marginal components getting increased size in only one direction.

    A test program of this class is:

      import java.awt.*;
      import java.awt.event.*;
    

    public class Border extends Frame implements WindowListener { private boolean isMainFrame;

    public Border(boolean isMain) { //Construct superclass with title super("Test Border Panel"); isMainFrame = isMain; this.addWindowListener(this); //Create user interface BorderPanel panel = new BorderPanel(); panel.add("North",new Button("North")); panel.add("South",new Button("South")); panel.add("West",new Button("West")); panel.add("East",new Button("East")); panel.add("Center",new Button("Center")); this.add(panel); //Pack and validate this.setSize(300,200); this.validate(); }

    //------------------------------------------------------------ // WindowListener //------------------------------------------------------------

    public void windowOpened(WindowEvent eve) { }

    public void windowActivated(WindowEvent eve) { }

    public void windowClosing(WindowEvent eve) { //Exit if is main window if (isMainFrame) System.exit(0); //Must be applet or child window dispose(); }

    public void windowClosed(WindowEvent eve) { }

    public void windowDeactivated(WindowEvent eve) { }

    public void windowIconified(WindowEvent eve) { }

    public void windowDeiconified(WindowEvent eve) { }

    //------------------------------------------------------------ // MAIN EXECUTION //------------------------------------------------------------

    public static void main(String[] args) { Frame frame = new Border(true); frame.show(); } }

    There is little advantage to using this class as it stands. It could be made more useful by adding some additional methods. For example, it might be nice to be able to specify the growth weights so that one of the marginal components could grow in both directions instead of the center component.

  3. Consider the following constructor for a numeric keypad:
      public class NumbPad extends Frame
      {
            see assignment
    
    1. Sketch the keypad that is produced by this code.

      The following image is the actual keypad that is produced by the frame running as an application:

      [NUMERIC KEYPAD]

      Note the kludge of putting extra space in the number buttons. This was done to force the default minimum size to approximate the width of the "Clear" and "Enter" buttons. The correct way to handle this problem is to use the ipadx member variable to force a wider button. The original code should have been:

          //Make enter and clear                            X Y W H
              buttonClr   = makeButton("Clear",    grid,gbc,0,0,1,1);
              buttonEnter = makeButton("Enter",    grid,gbc,3,3,1,2);
          //Pad width to approximate width of Clear
              gbc.ipadx = 50;
          //Create operations                       X Y W H
              buttonDiv   = makeButton("/",grid,gbc,1,0,1,1);
              buttonMul   = makeButton("*",grid,gbc,2,0,1,1);
              buttonSub   = makeButton("-",grid,gbc,3,0,1,1);
              buttonSub   = makeButton("+",grid,gbc,3,1,1,2);
              buttonDot   = makeButton(".",grid,gbc,2,4,1,1);
          //Make digits
              button0     = makeButton("0",grid,gbc,0,4,2,1);
              button1     = makeButton("1",grid,gbc,0,3,1,1);
              button2     = makeButton("2",grid,gbc,1,3,1,1);
              button3     = makeButton("3",grid,gbc,2,3,1,1);
              button4     = makeButton("4",grid,gbc,0,2,1,1);
              button5     = makeButton("5",grid,gbc,1,2,1,1);
              button6     = makeButton("6",grid,gbc,2,2,1,1);
              button7     = makeButton("7",grid,gbc,0,1,1,1);
              button8     = makeButton("8",grid,gbc,1,1,1,1);
              button9     = makeButton("9",grid,gbc,2,1,1,1);
      

    2. What is the rationale behind the width and height that are specified in the setSize() method call?

      The setSize() is used to make the keypad larger than it would be using the default preferred sizes of the buttons. The ratio of 200 wide by 250 high is (4 * 50) by (5 * 50) to match the grid size. This should make the number buttons square. Setting ipady to 50 should accomplish the same effect if pack() is used instead of setSize().

  4. StoneAge Computing wants to port some of their existing applications to modern technology. Their current user interface, which is character based, is shown in the following diagram.

    See Assignment

    Write a Java class called MainWindow that extends Frame to implement this interface. Assume that the main display is a text area that uses the monospaced Courier font. The main display should get all of the additional height if the window is resized. Include a main() method that can be used to quickly test the appearance of the interface.

    The first step is to lay a grid over the user interface to guide our layout efforts. As the diagram shows, the grid cells can be different heights by assigning zero height weights to all but the text area. Use this button to see the resulting interface.

    [STONEAGE INTERFACE GRID]

    The following will not work in browsers that do not yet support JDK 1.1.6.

    The solution is similar to the button bag example. The setGbcGrid() and makeButton() helper methods are the same. This code includes a new makeLabel() helper method:

        private Label makeLabel(String text,
            GridBagLayout grid, GridBagConstraints gbc,
            int xLoc, int yLoc, int width, int height,
            int alignment)
        {
        //Create label
            Label label = new Label(text,alignment);
        //Set grid parameters
            setGbcGrid(gbc,xLoc,yLoc,width,height);
            grid.setConstraints(label,gbc);
        //Add label to frame
            this.add(label);
        //Return label reference so it can be saved
            return(label);
        }
    
    Then, the constructor can build the interface:
      //User interface components
          private Label    screenTitle;
          private Label    systemDate;
          private TextArea mainDisplay;
          private Label    promptMess;
          private Label    statusMess;
          private Button[] actionButton;
    

    public MainWindow(boolean isMain) { //Construct superclass with title super("MainWindow Interface"); isMainFrame = isMain; this.addWindowListener(this); //Create grid bag layout GridBagLayout grid = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); //Set frame layout to grid bag this.setLayout(grid); //Assume grow in both directions gbc.fill = GridBagConstraints.BOTH; //Let all grow equally in horizontal direction gbc.weightx = 100.0; gbc.weighty = 0.0; //Make top labels screenTitle = makeLabel(" Screen Title",grid,gbc,0,0,3,1,Label.LEFT); screenTitle = makeLabel("System Date ", grid,gbc,3,0,3,1,Label.RIGHT); //Make text area with high vertical weight gbc.weighty = 100.0; mainDisplay = new TextArea(21,80); mainDisplay.setFont(new Font("Courier",Font.PLAIN,14)); setGbcGrid(gbc,0,1,6,1); grid.setConstraints(mainDisplay,gbc); this.add(mainDisplay); gbc.weighty = 0.0; //Make prompt and status labels promptMess = makeLabel("Prompt Message",grid,gbc,0,2,6,1,Label.CENTER); statusMess = makeLabel("Status Message",grid,gbc,0,3,6,1,Label.CENTER); //Make action buttons actionButton = new Button[6]; for (int col = 0; col < 6; col++) { actionButton[col] = makeButton("Action",grid,gbc,col,4,1,1); } //Pack and validate this.setSize(480,360); this.validate(); }

    In reality, the labels and buttons would not include the text shown here. The label and button text would dynamically change as the application was executing. The complete source code is available.


Page: (Top) (Prev) (Next) Class: (Outline) (Summary) (Assign) (Answer) Course: (Cover) (Content) (Glossary)

Prepared by David L. March -- Last Revised on October 19, 1998
COPYRIGHT © 1998 BY DAVID L. MARCH