A Class for Rectangles

 

Background.  Now we will develop another rather rudimentary classes to illustrate some of the principles and issues we have worked with so far.  This second example relates to rectangles.  We keep it simple and don't really do any drawing.  But we will get a length and width from a user and compute relevant things such as the area and the perimeter.

Whether you are aware of it or not, the length and width are probably the most salient measures related to a rectangle.  If you know it you should be able to find out just about anything else you want about the rectangle.

So, ultimately, our rectangles will be represented by two numbers in the computer.  They are not represented by a drawn rectangle.  We will see this sort of pattern repeat mainly because methods are invoked using an n-tuple notation.

methodName(arg1, arg2, arg3 ... argn)

Remember, it took three numbers to represent the time, or what are often called three-tuples.  One number to represent a circle, through what might be called a one-tuple.  Now we will be working with two-tuples.

You should call the following file Rectangle.java and save it in its own directory. Whether or not you want to create a package is up to you.  You will notice we sometimes make use of the this reference rather than referring to an instance of an object by its name.

 

import java.text.DecimalFormat;

public class Rectangle extends Object
{

private double length;
private double width;

public Rectangle( )
{

setRectangle(0,0);

}

public Rectangle(double len, double wid)
{

setRectangle(len,wid);

}

public void setRectangle(double len, double wid)
{

length = len;
width = wid;

}

public void setLength(double len)
{

length = len;

}

public void setWidth(double wid)
{

width = wid;

}

public double getLength( )
{

return length;

}

public double getWidth( )
{

return width;

}

public double Area( Rectangle input )
{

return this.getLength( ) * this.getWidth( );

}

public double Perimeter( Rectangle input )
{

return (2 * this.getLength( )) + (2 * this.getWidth( ));

}


public String toPrecisionTwoString(double someNumber)
{

DecimalFormat twoDecimalPlaces = new DecimalFormat("0.00");
return twoDecimalPlaces.format(someNumber);

}

}

 

You should compile this, likely with the more typical

javac Rectangle.java

We start with a discussion of the code and methods.

  • import java.text.DecimalFormat

  • the overall inclusive class is called Rectangle that extends Object

    • declare an instance variable double length

    • declare an instance variable double width

 

  • define a constructor Rectangle( )

    • receives no arguments

    • uses a later method setRectangle( ) to initialize the length and width to zero

 

  • define a constructor Rectangle( )

    • receives two double precision arguments len and wid

    • uses a later method setRectangle( ) to initialize the length of the object to len and the width of the object to wid

 

  • a setLength( ) method is declared and developed
    • it receives a single double precision argument
      • len for the length
    • it assigns the instance variable length equal to the len that is passed

 

  • a setWidth( ) method is declared and developed
    • it receives a single double precision argument
      • wid for the width
    • it assigns the instance variable width equal to the wid that is passed

 

  • a getLength( ) method is declared and developed
    • it receives no arguments
    • it returns the length of the object

 

  • a getWidth( ) method is declared and developed
    • it receives no arguments
    • it returns the width of the object

 

  • an Area( ) method is declared and developed
    • it receives one argument
      • an object of type Rectangle
    • it returns a double precision number representing the area of the rectangle
    • the area is computed using the length times the width
      • the length is obtained using this.getLength( )
      • the width is obtained using this.getWidth( )

 

  • a Perimeter( ) method is declared and developed
    • it receives one argument
      • an object of type Rectangle
    • it returns a double precision number representing the perimeter of the rectangle
    • the area is computed using 2 times the length plus 2 times the width
      • the length is obtained using this.getLength( )
      • the width is obtained using this.getWidth( )

 

  • a toPrecisionTwoString( ) method is declared and developed
    • it receives one double precision argument
    • it returns a String
    • it makes use of the DecimalFormat class in the text package to create a format that always has exactly two places after the decimal
    • it returns whatever double precision number was passed to it in this format as a string

 

Now you need the following RectangleTestGUI.java to construct/instantiate a Rectangle object and work with it.

 

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class RectangleTestGUI extends JApplet implements ActionListener
{

// GUI components
JLabel lblLength, lblWidth, lblArea, lblPerimeter, lblCompute;
JTextField txtLength, txtWidth, txtArea, txtPerimeter;
JButton cmdCompute;
// boolean variable to report about input validity
boolean validInput;
double lengthInput;
double widthInput;
// panels for the GUI
JPanel panDevelop, panGUI;

public void init( )
{

JPanel panGUI = new JPanel( );
panGUI = createGUI( );

setContentPane(panGUI);

}

public JPanel createGUI( )
{

JPanel panDevelop = new JPanel( );
panDevelop.setLayout(new GridLayout(5, 2, 8, 8));

// label and text field for rectangle length
lblLength = new JLabel("Set Length: ", SwingConstants.RIGHT);
txtLength = new JTextField(10);
panDevelop.add(lblLength);
panDevelop.add(txtLength);

// label and text field for rectangle width
lblWidth = new JLabel("Set Width: ", SwingConstants.RIGHT);
txtWidth = new JTextField(10);
panDevelop.add(lblWidth);
panDevelop.add(txtWidth);

// label and button to invoke computation
lblWidth = new JLabel("Click to Solve:", SwingConstants.RIGHT);
panDevelop.add(lblWidth);
cmdCompute = new JButton("Compute");
cmdCompute.addActionListener(this);
panDevelop.add(cmdCompute);

// label and text field for reporting the area
lblArea = new JLabel("The area is: ", SwingConstants.RIGHT);
txtArea = new JTextField(10);
txtArea.setEditable(false);
panDevelop.add(lblArea);
panDevelop.add(txtArea);

// label and text field for reporting the perimeter
lblPerimeter = new JLabel("The perimeter is: ", SwingConstants.RIGHT);
txtPerimeter = new JTextField(10);
txtPerimeter.setEditable(false);
panDevelop.add(lblPerimeter);
panDevelop.add(txtPerimeter);

return panDevelop;

}

public void actionPerformed(ActionEvent e)
{

// call the method to obtain and validate input
if (validateInput( ))
{

if (e.getSource() == cmdCompute)
{

// instantiate a new rectangle with the user's inputs
Rectangle one = new Rectangle(lengthInput, widthInput);
// compute the area
// cast it to a string with two decimal places
// set the text in txtArea

txtArea.setText(one.toPrecisionTwoString(one.Area(one)));
// compute the perimeter
// cast it to a string with two decimal places
// set the text in txtPerimeter

txtPerimeter.setText(one.toPrecisionTwoString(one.Perimeter(one)));

}

}

}

public boolean validateInput( )
{

validInput = true;
String errorMessage = "";

try
{

lengthInput = Double.parseDouble(txtLength.getText( ));

}

catch (NumberFormatException nfeDouble)
{

// increment error message when input can't be parsed to double
errorMessage = errorMessage + "You need to enter a number for the length\n";
// set boolean variable to false when
// received an invalid input
validInput = false;
// blanking out input
// when input is invalid
txtLength.setText("");

}

try
{

widthInput = Double.parseDouble(txtWidth.getText());

}

catch (NumberFormatException nfeDouble)
{

// increment error message when input can't be parsed to double
errorMessage = errorMessage + "You need to enter a number for the width\n";
// set boolean variable to false when
// received an invalid input

validInput = false;
// blanking out input
// when input is invalid

txtWidth.setText("");

}

if (!validInput)
{

JOptionPane.showMessageDialog(null, errorMessage, "Input Error", JOptionPane.ERROR_MESSAGE);
txtArea.setText("");
txtPerimeter.setText("");

}

return validInput;

}

}

 

You do not need to specify any special path in the compilation command.

javac RectangleTestGUI.java

You should run this code and play with the GUI some before we dig into it.

The HTML file follows and should be called RectangleTestGUI.html.

 

<html>
<applet code="RectangleTestGUI.class" width=300 height=200>
</applet>
</html>

 

If you try to click on the command button and don't have an appropriate input you should see something like the following.

 

 

With acceptable numbers in the length and width text fields you should see something more like the following.

 

 

Notice the two decimal places on the area and the perimeter even though the inputs had more.

Now we will discuss the code.

  • we need to import the javax.swing.* package
  • import java.awt.*
  • import java.awt.event

 

  • the overall inclusive class is called CircleTestGUI which extends JApplet and implements ActionListener
    • declare the GUI components
      • a label for the length input = lblLength
      • a text field for the length input = txtLength
      • a label for the width input = lblWidth
      • a text field for the width input = txtWidth
      • a label for outputting the area = lblArea
      • a text field for outputting the area = txtArea
      • a label for outputting the perimeter = lblPerimeter
      • a text field for outputting the perimeter = txtPerimeter
      • a label to tell the user to click the compute button = lblCompute
      • a button to cause the program to compute = cmdCompute
      • a panel to contain the GUI called panGUI
      • a panel for developing the GUI called panDevelop
    • declare the variables associated with user inputs
      • a boolean validInput to indicate whether the user's inputs pass the program's validity tests
      • initialize and declare a variable for the user's length input = lengthInput
      • initialize and declare a variable for the user's width input = widthInput

 

  • the init( ) method
    • instantiates a panel to be the panel that contains all the other panels called panGUI
    • calls the methods to create the GUI called createGUI( )
    • sets the content pane for the applet to be panGUI

 

  • the actionPerformed( ) method
    • calls the validateInput( ) method to retrieve and validate the user's input
    • if the input is acceptable
      • determines the source of the user's click
      • if the user clicks the compute button
        • creates a new instance of a Circle object called One set by the user's inputs
        • echoes the input in the txtEchoInput text field
          • gets the radius using getRadius( )
          • sets the text using the built in setText( ) method
        • updates the display in the txtAreaOutput text field
          • calls the computeArea( ) method in the Circle class
          • uses the class method toPrecisionFourString( ) to format it for display
          • sets the text using the built in setText( ) method
        • updates the display in the txtCircumferenceOutput text field
          • calls the computeCircumference( ) method in the Circle class
          • uses the class method toPrecisionFourString( ) to format it for display
          • sets the text using the built in setText( ) method
      • destroys the Circle object called One

 

  • createGUI( )
    • creates the panel to contain the input components
    • sets the layout to a GridLayout with five rows and two columns
    • instantiates the appropriate JLabels and JTextFields
    • instantiates a JButton
    • sets editability properties appropriately
    • returns this panel to the calling location

 

  • the actionPerformed( ) method
    • determines the source of the user's click
    • if the user clicks the compute button
      • calls the validateInput( ) method to retrieve and validate the user's input
      • if the input is acceptable
        • creates a new instance of a Rectangle object called one set by the user's inputs
        • updates the display in the txtArea text field
          • calls the Area( ) method in the Rectangle class
          • uses the class method toPrecisionTwoString( ) to format it for display
          • sets the text using the built in setText( ) method
        • updates the display in the txtPerimeter text field
          • calls the Perimeter( ) method in the Circle class
          • uses the class method toPrecisionTwoString( ) to format it for display
          • sets the text using the built in setText( ) method

 

  • the validateInput( ) method
    • initializes validInput to true
    • uses a try block to
      • get the text from txtLength
      • parse it as a double
    • uses a catch block if it can't be parsed as a double to
      • appends an error to the errorMessage
      • set validInput to false
      • set the txtLength to blank
    • uses a try block to
      • get the text from txtWidth
      • parse it as a double
    • uses a catch block if it can't be parsed as a double to
      • appends an error to the errorMessage
      • set validInput to false
      • set the txtWidth to blank
    • if some input is invalid
      • errorMessage is displayed using the showMessageDialog( ) method of the JOptionPane class
      • sets the txtArea contents to blank
      • sets the txtPerimeter contents to be blank
    • returns validInput

 

Now we will move on to one of the classic examples for user class development, working with fractions.