I/O in AP Java - Western Washington University

advertisement
I/O in AP Java
Enjoyable, Meaningful, NonDistracting I/O in AP Java
Ken Lambert, Washington and Lee University
Martin Osborne, Western Washington University
Copyright 2002
Free Supplemental Materials
www.cs.wwu.edu/martin
 Slides for this talk
 Software packages
– TerminalIO
– TurtleGraphics
– BreezySwing
Languages for Introductory
Programming
Fortran (60's)
 PL/1 (70's)
 Pascal and Modula (80's)
 C++ (90's)
 Java (2000 and beyond)

Why Java?
Pascal a teaching language
 C++ a developer's language
 Java a bit of both

– For teaching
• Smaller, simpler syntax than C++
– For developer's
• Safe, portable, vast supporting libraries
C++ I/O

Stream I/O
–
–
–
–
–

Simple, flexible
Supports both terminal and files
cin, cout for console
Stream objects for files
Suitable for introductory course
GUI's
– Platform dependent
– Complex
– Not suitable for introductory course
Java I/O

Stream I/O
– Moderately difficult
– Several simple patterns cover basic situations
– Somewhat suitable for introductory course

GUIs
– Platform independent
– Complex
• but several complex patterns cover basic situations
– Doable but not really suitable for introductory
course
AP I/O Requirements
Terminal output with System.out
 Package supported stream input

– Basic read functions for intrinsic data types
Advantage of AP Approach
Leaves more time for everything else
 Including some I/O that is

– Enjoyable
– Meaningful
– Non-distracting
Most Basic Program Structure
import …;
public class <ProgramName> {
public static void main(String [] args) {
… statements…
}
}
Console Applications
Temperature Conversion
User Interface
Enter degrees Fahrenheit: 212
The equivalent in Celsius is 100.0
Implementation
import TerminalIO.KeyboardReader;
public class Convert {
public static void main(String [] args) {
double fahrenheit;
double celsius;
KeyboardReader reader = new KeyboardReader();
fahrenheit = reader.readDouble("Enter degrees Fahrenheit: ");
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
System.out.println("The equivalent in Celsius is " + celsius);
}
}
Menu Driven Conversion
1) Convert from Fahrenheit to Celsius
2) Convert from Celsius to Fahrenheit
3) Quit
Enter your option: 1
Enter degrees Fahrenheit: 212
Degrees Celsius = 100.0
1) Convert from Fahrenheit to Celsius
2) Convert from Celsius to Fahrenheit
3) Quit
Enter your option: 2
Etc…
Implementation (1 of 2)
import TerminalIO.*;
public class ConvertWithMenu {
public static void main (String [] args) {
KeyboardReader reader = new KeyboardReader();
double fahrenheit, celsius;
String menu;
//The multiline menu
int menuOption;
//The user's menu selection
menu = "\n1) Convert from Fahrenheit to Celsius"
+ "\n2) Convert from Celsius to Fahrenheit"
+ "\n3) Quit"
+ "\nEnter your option: ";
Implementation (2 of 2)
do {
menuOption = reader.readInt(menu);
System.out.println ("");
if (menuOption == 1){
fahrenheit = reader.readDouble("Enter degrees Fahrenheit: ");
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
System.out.println ("Degrees Celsius = " + celsius);
}else if (menuOption == 2){
celsius = reader.readDouble("Enter degrees Celsius: ");
fahrenheit = celsius * 9.0 / 5.0 + 32.0;
System.out.println ("Degrees Fahrenheit = " + fahrenheit);
}else if (menuOption != 3){
System.out.println ("Invalid option");
}
} while (menuOption != 3);
}
}
Formatted Output
The
The
The
The
The
The
The
The
The
The
number
number
number
number
number
number
number
number
number
number
with
with
with
with
with
with
with
with
with
with
precision
precision
precision
precision
precision
precision
precision
precision
precision
precision
0:
1
1:
1.2
2:
1.23
3:
1.235
4:
1.2346
5:
1.23456
6: 1.234560
7: 1.2345600
8:1.23456000
9:**********
Implementation
import BreezySwing.Format;
public class TerminalFormatDemo {
public static void main (String [] args) {
double number = 1.23456;
for (int i = 0; i <= 9; i++){
String str = "The number with precision "
+ i + ":"
+ Format.justify ('r', number, 10, i);
System.out.println (str);
}
}
}
Temperature Conversion
Revisited
User Interface
Enter degrees Fahrenheit: 212
The equivalent in Celsius is 100.0
Native Implementation (1 of 2)
import java.io.*;
public class Convert{
public static void main (String[] args){
…
try{
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(reader);
… = Double.parseDouble(buffer.readLine());
… = Integer.parseInt(buffer.readLine());
…
}catch(Exception e){
System.err.println("Input error -- " + e.toString());
}
}
}
Native Implementation (2 of 2)
import java.io.*;
public class Convert{
public static void main (String[] args){
double fahrenheit;
double celsius;
try{
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(reader);
System.out.print("Enter degrees Fahrenheit: ");
fahrenheit = Double.parseDouble(buffer.readLine());
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
System.out.println("The equivalent in Celsius is " + celsius);
}catch(Exception e){
System.err.println("Input error -- " + e.toString());
}
}
}
Factoring Out the Complexity
with a static method (1 of 2)
import java.io.*;
public class Convert2{
public static void main (String[] args){
double fahrenheit;
double celsius;
fahrenheit = readDouble("Engter degrees Fahrehheit: ");
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
System.out.println("The equivalent in Celsius is " + celsius);
}
Factoring Out the Complexity
with a static method (2 of 2)
public static double readDouble(String prompt){
double theNumber;
try{
InputStreamReader reader =
new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(reader);
System.out.print(prompt);
theNumber = Double.parseDouble(buffer.readLine());
return theNumber;
}catch(Exception e){
System.err.println("Input error -- " + e.toString());
return 0;
}
}
}
Factoring Out the Complexity
with a supporting class (1 of 2)
public class Convert3 {
public static void main(String [] args) {
double fahrenheit;
double celsius;
KeyboardReader reader = new KeyboardReader();
fahrenheit = reader.readDouble("Enter degrees Fahrenheit: ");
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
System.out.println("The equivalent in Celsius is " + celsius);
}
}
Factoring Out the Complexity
with a supporting class (2 of 2)
import java.io.*;
public class KeyboardReader{
public double readDouble(String prompt){
double theNumber;
try{
InputStreamReader reader =
new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(reader);
System.out.print(prompt);
theNumber = Double.parseDouble(buffer.readLine());
return theNumber;
}catch(Exception e){
System.err.println("Input error -- " + e.toString());
return 0;
}
}
}
Illustrating Concepts
with Turtle Graphics
Draw a Square
Instantiating and sending messages to an object
import TurtleGraphics.StandardPen;
public class DrawSquare {
public static void main (String [] args) {
Implementation
// Instantiate a pen object
StandardPen pen = new StandardPen();
// Lift the pen, move it to the square's top left corner,
// and lower it again
pen.up();
pen.move(25);
pen.turn(90); pen.move(25);
pen.down();
// Draw the square
pen.turn(90); pen.move(50);
pen.turn(90); pen.move(50);
pen.turn(90); pen.move(50);
pen.turn(90); pen.move(50);
}
}
Draw a 100-gon
Using for-statements
Implementation
import TurtleGraphics.StandardPen;
public class Draw100gon {
public static void main (String [] args) {
int i;
StandardPen pen = new StandardPen();
// Lift, move to top of circle, lower
pen.up();
pen.move(25);
pen.turn(90); pen.move(0.8);
pen.down();
// Draw the 100gon
for (i = 1; i <= 100; i++){
pen.turn(3.6);
pen.move(1.6);
}
}
}
Smiley Face
User defined classes
Outline of Class
public class SmilingFace {
public SmilingFace(){...}
public SmilingFace(double x, double y){...}
public void draw(){
public void erase(){
public void move(double x, double y){...}
private void drawCircle(double x, double y, double r){...}
private void drawLine(double x1, double y1,
double x2, double y2){...}
private StandardPen pen;
private double xPosition, yPosition;
}
import TurtleGraphics.*;
import TerminalIO.*;
public class TestSmilingFace {
public static void main (String[] args){
KeyboardReader reader = new KeyboardReader();
double x, y, radius;
Using the Class
x = reader.readDouble("Initial x position: ");
y = reader.readDouble("Initial y position: ");
SmilingFace face = new SmilingFace(x, y);
face.draw ();
while (true){
x = reader.readDouble("New x position: ");
y = reader.readDouble("New y position: ");
face.erase();
face.move(x, y);
face.draw();
}
}
Implementation
of Class (1 of 4)
import TurtleGraphics.*;
import java.awt.Color;
public class SmilingFace {
private StandardPen pen;
private double xPosition, yPosition;
public SmilingFace(){
xPosition = 0;
yPosition = 0;
pen = new StandardPen();
pen.setColor(Color.red);
}
public SmilingFace(double x, double y){
this();
xPosition = x;
yPosition = y;
}
Implementation of Class (2 of 4)
public void erase(){
pen.setColor(Color.white);
draw();
pen.setColor(Color.red);
}
public void move(double x, double y){
xPosition = x;
yPosition = y;
}
public void draw(){
double radius = 50.0;
Implementation
of Class (3 of 4)
// Draw the outline of the face
drawCircle(xPosition, yPosition, radius);
// Draw the left and right eye.
drawCircle(xPosition - radius / 2.5, yPosition + radius / 3, radius / 4);
drawCircle(xPosition + radius / 2.5, yPosition + radius / 3, radius / 4);
// Draw the horizontal part of the mouth
drawLine(xPosition - radius / 3, yPosition - radius / 2,
xPosition + radius / 3, yPosition - radius / 2);
// Draw the left and right smile line
drawLine(xPosition - radius / 3 , yPosition - radius / 2,
xPosition - radius / 3 - 5, yPosition - radius / 2 + 5);
drawLine(xPosition + radius / 3 , yPosition - radius / 2,
xPosition + radius / 3 + 5, yPosition - radius / 2 + 5);
}
Implementation of Class (4 of 4)
private void drawCircle(double x, double y, double r){
double side = 2.0 * Math.PI * r / 120.0;
pen.up();
pen.move(x + r, y - side / 2.0);
pen.setDirection(90);
pen.down();
for (int i = 0; i < 120; i++){
pen.move(side);
pen.turn(3);
}
}
private void drawLine(double x1, double y1, double x2, double y2){
pen.up();
pen.move(x1, y1);
pen.down();
pen.move(x2, y2);
}
}
Fractals
Recursion
Implementation (1 of 2)
import java.awt.Color;
import TurtleGraphics.*;
public class Recursion {
public static void main (String [] args) {
Pen pen = new StandardPen();
pen.setWidth(1);
for (int i = 1; i <= 6; i++){
pen.up();
pen.move(-100, 245 - 70 * i);
pen.down();
pen.setDirection(0);
drawFractal(i, pen, 200);
}
}
Implementation (2 of 2)
private static void drawFractal(int depth, Pen pen, double length){
if (depth <= 1)
pen.move(length);
else{
drawFractal(depth - 1, pen, length / 3);
pen.turn(60);
drawFractal(depth - 1, pen, length / 3);
pen.turn(-120);
drawFractal(depth - 1, pen, length / 3);
pen.turn(60);
drawFractal(depth - 1, pen, length / 3);
}
}
}
Drawing in Applets
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
Implementation
public class Shapes extends Applet{
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D)g;
Rectangle rectangle = new Rectangle(50, 50, 100, 50);
Ellipse2D.Double ellipse = new Ellipse2D.Double(50, 50, 100, 50);
Point2D.Double point1 = new Point2D.Double(50, 50);
Point2D.Double point2 = new Point2D.Double(150, 100);
Line2D.Double line = new Line2D.Double(point1, point2);
g2.draw(rectangle);
g2.draw(ellipse);
g2.draw(line);
}
}
GUIs
A Simple GUI
Breezy Implementation (1 of 4)
import javax.swing.*;
import BreezySwing.*;
public class ConvertWithGUI extends GBFrame{
private JLabel
private JLabel
private DoubleField
private DoubleField
private JButton
private JButton
fahrenheitLabel;
celsiusLabel;
fahrenheitField;
celsiusField;
fahrenheitButton;
celsiusButton;
Breezy Implementation (2 of 4)
public ConvertWithGUI(){
fahrenheitLabel = addLabel
("Fahrenheit" ,1,1,1,1);
celsiusLabel
= addLabel
("Celsius" ,1,2,1,1);
fahrenheitField = addDoubleField (32.0
,2,1,1,1);
celsiusField
= addDoubleField (0.0
,2,2,1,1);
fahrenheitButton = addButton
(">>>>>>" ,3,1,1,1);
celsiusButton
= addButton
("<<<<<<" ,3,2,1,1);
}
Breezy Implementation (3 of 4)
public void buttonClicked (JButton buttonObj){
double fahrenheit, celsius;
if (buttonObj == fahrenheitButton){
fahrenheit = fahrenheitField.getNumber();
celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
celsiusField.setNumber (celsius);
}else{
celsius = celsiusField.getNumber();
fahrenheit = celsius * 9.0 / 5.0 + 32.0;
fahrenheitField.setNumber (fahrenheit);
}
}
Breezy Implementation (4 of 4)
public static void main (String[] args){
ConvertWithGUI theGUI = new ConvertWithGUI();
theGUI.setSize (250, 100);
theGUI.setVisible (true);
}
Native Implementation (1 of 6)
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ConversionWithSwing extends JFrame{
private JLabel
fahrenheitLabel;
private JTextField fahrenheitField;
private JLabel
celsiusLabel;
private JTextField celsiusField;
private JButton
fahrenheitButton;
private JButton
celsiusButton;
Native Implementation (2 of 6)
public ConversionWithSwing(){
fahrenheitLabel = new JLabel ("Fahrenheit");
celsiusLabel = new JLabel ("Celsius");
fahrenheitField = new JTextField ("212", 6); // 6 columns wide
celsiusField = new JTextField ("100", 6); // 6 columns wide
fahrenheitButton = new JButton (">>>>>>");
celsiusButton = new JButton ("<<<<<<");
Native Implementation (3 of 6)
Container contentPane = getContentPane();
contentPane.setLayout (new FlowLayout());
contentPane.add (fahrenheitLabel);
contentPane.add (celsiusLabel);
contentPane.add (fahrenheitField);
contentPane.add (celsiusField);
contentPane.add (fahrenheitButton);
contentPane.add (celsiusButton);
fahrenheitButton.addActionListener(new MyActionListener());
celsiusButton.addActionListener(new MyActionListener());
addWindowListener(new MyWindowAdapter());
}
Native Implementation (4 of 6)
public static void main (String[] args){
ConversionWithSwing theGUI = new ConversionWithSwing();
theGUI.setSize (200, 125);
theGUI.setVisible (true);
}
Native Implementation (5 of 6)
private class MyActionListener implements ActionListener{
public void actionPerformed (ActionEvent event){
double fahrenheit, celsius;
String str;
Object source = event.getSource();
if (source == fahrenheitButton){
str = fahrenheitField.getText().trim();
fahrenheit = Double.parseDouble(str);
celsius = (fahrenheit - 32) * 5 / 9;
celsiusField.setText ("" + celsius);
}else{
str = celsiusField.getText().trim();
celsius = Double.parseDouble(str);
fahrenheit = celsius * 9 / 5 + 32;
fahrenheitField.setText ("" + fahrenheit);
}
}
}
Native Implementation (6 of 6)
private class MyWindowAdapter extends WindowAdapter{
public void windowClosing (WindowEvent e){
System.exit(0);
}
}
}
Drawback of Flow Layout
Fields move around when window
resized
 Solution – use a gridbag layout

– Unfortunately, considerably more complex
Summary
AP Java has minimal I/O requirements
 Take advantage of this to

– Have fun and
– Add interest

While
– providing useful skills and
– Avoiding unnecessary complexity
Download