CS100A Lecture 16 27 October 1998 Assignment 7: A Checker-playing program: learning about GUIs and working with a well-designed and welldocumented program GUI: Graphical User Interface Project designed to show advantage of “object-oriented programming”. The awt (abstract window toolkit) contains many classes --and subclasses-- and extending some of them is an integral part of implementing a GUI. This project will NOT require you to write code that deals with the GUI; the assignment gives you only an introduction to the topic. Your programming will deal with the code that manipulates the checkers represented in a two-dimensional array. And a lot of it requires only calling already-written methods. CS100A, Lecture 16, 27 October 1998 1 Some classes in the abstract window toolkit class Frame: An instance is a “window” on the screen. It can contain “components”. You get to say where the components go. Frame Window Container is a subclass of Window is a subclass of Container is a subclass of Component Some components that can appear in a Frame instance of Button: a button to be clicked with mouse. instance of Label: a String that the user can’t change. instance of TextField: a string that the user can change instance of TextArea:2-dimensional text area, changeable instance of Canvas: Can be drawn on using Graphics class Event: An instance describes some event, like “mouse up”, “mouse drag”, “click on a button”, “click on the window-destroy field”, a keystroke. CS100A, Lecture 16, 27 October 1998 2 (part of) class Frame public class java.awt.Frame extends java.awt.Window implements java.awt.MenuContainer { // possible cursor types for method setCursor public final static int CROSSHAIR_CURSOR; § public final static int DEFAULT_CURSOR; public final static int HAND_CURSOR; ... public Frame(String title); public void dispose(); public String getTitle(); public void setTitle(String title); public boolean isResizable(); public void setResizable(boolean resizable); public int getCursorType(); public void setCursor(int cursorType); CS100A, Lecture 16, 27 October 1998 3 part of class Window (superclass of Frame) public class java.awt.Window extends java.awt.Container { //Constructor public Window(Frame parent); // Remove, get rid of, this window public void dispose ( ); // Lay out the components in window with preferred size public void pack( ); // Make this window visible public void show( ); // Put window behind other windows public void toBack( ); // Put window in front of other windows public void toFront (); CS100A, Lecture 16, 27 October 1998 4 part of class Container (superclass of Window) public class java.awt.Container extends java.awt.Component { // Add component comp to the container public Component add(Component comp); // remove comp from the container public void remove(Component comp); // Tell container what layout manager to use public void setLayout(LayoutManager mgr); // Lay out the components in container with // preferred size public void pack( ); CS100A, Lecture 16, 27 October 1998 5 part of class Component (superclass of Component) public class java.awt.Component { // Process action, return “action has been handled” public boolean action(Event evt, Object what); // Handle event, return “event has been handled” public boolean handleEvent(Event evt); // Make component insensitive (sensitive) to use input public void disable( ); public void enable( ); // repaint this component public void repaint( ); // Change the width and height to w and h public void resize(int w, int h); // Set the background color to c public void setBackground(Color c); // Make sure the component is seen on the screen public void show( ); CS100A, Lecture 16, 27 October 1998 6 Layout Manager Used to place and control components on a Frame. Several layout managers --simple ones give programmer less control, the more complex ones give more There are also programs that help you build GUIs without having to do all the programming. Look briefly at one layout manager, GridBagLayout. Requires an instance of another class, GridBagConstraints. Basically, to add a new component to the Frame, you set the properties you want it to have in the instance of GridBagConstraints and then call a method add. CS100A, Lecture 16, 27 October 1998 7 GridBagLayout and GridBagConstraints 0 0 1 2 3 4 1 2 3 4 5 6 7 AAAAA BBBB BBBB A: TextField CCCCCCCCCCC CCCCCCCCCCC CCCCCCCCCCC CCCCCCCCCCC B: Button C: TextArea A frame with a TextField, a Button, and a TextArea gbl= new GridBagLayout(); gbc= new GridBagConstraints(); setLayout(gbl); TextField tf= new TextField(“a text field”); TextArea ta= new TextArea(“text\narea”); Button b= new Button(“name on button”); add(tf,gbl,gbc, 0,0, 3,1, 100,100); add(ta,gbl,gbc, 1,1, 2,2, 100,100); add(tf,gbl,gbc, 3,2, 5,3, 100,100); CS100A, Lecture 16, 27 October 1998 8 Following slides: class Experiment, which is an extension of Frame. It has several components in the frame. class TrivialApplication, which defines a variable that can contain an Experiment. class CheckersSquare (stripped down version), a component of class Canvas. We spend some time demonstrating and investigating these classes. You can download these three classes in a single file from our web site (look for “assignment 7”). Start a new codewarrior project, using the Java application stationery (not the CUCS stationery). Then replace file TrivialApplication.java with this file (of the same name). CS100A, Lecture 16, 27 October 1998 9 // Frame to illustrate the awt. public class Experiment extends Frame { // Components that go in the frame CheckersSquare sq; Label lab; TextField textf; TextArea texta; // Titles for buttons String[ ] bs= {"new game", "quit"}; // The layout and constraint variables for this frame GridBagLayout gbl; GridBagConstraints gbc; final int xw= 100; // Weights for all the components final int yw= 100; // when they are resized (class Experiment to be continued) CS100A, Lecture 16, 27 October 1998 10 // Constructor: a frame with various components public Experiment() { super("Experiment"); gbl= new GridBagLayout(); gbc= new GridBagConstraints(); setFont(new Font("Dialog", Font.PLAIN, 10)); setLayout(gbl); gbc.fill= gbc.BOTH; sq= new CheckersSquare(0,0); add(sq,gbl,gbc,0,0,1,1,xwt,yw); gbc.fill= gbc.BOTH; lab= new Label("A label at (1,1)"); add(lab, gbl,gbc,1,1,1,1,xw,yw); textf= new TextField("A TextField at (1,2)"); add(textf,gbl,gbc,1,2,1,1,xw,yw); texta= new TextArea("A TextArea\nat (1,3)"); add(texta,gbl,gbc,1,3,1,1,xw,yw); add(new Button(bs[0]),gbl,gbc, 2,0, 1,1, xw,yw); add(new Button(bs[1]),gbl,gbc, 3,0, 1,1, xw,yw); pack( ); move(150,50); show(); setResizable(false); CS100A, Lecture 16, 27 } October 1998 11 // Add component c to gbl with constraints gbc at position // (x,y). Component c takes w columns and r rows, and is // weighted (wx, wy). private void add(Component c, GridBagLayout gbl, GridBagConstraints gbc, int x, int y, int w, int h, int wx, int wy) {gbc.gridx= x; gbc.gridy= y; gbc.gridwidth= w; gbc.gridheight= h; gbc.weightx= wx; gbc.weighty= wy; gbl.setConstraints(c, gbc); add(c); } (class Experiment to be continued) CS100A, Lecture 16, 27 October 1998 12 // If button was pressed, process it; otherwise, let method // action in the superclass process it public boolean action(Event e, Object arg) { if (arg.equals(buttons[0])) { // Handle press of "New game" and return true System.out.println("\"new game\" pressed"); return true;} if (arg.equals(buttons[1])) { // Handle press of "Quit" and return true System.out.println("\"Quit\" pressed"); System.out.println("TextField is: \"" + textf.getText( ) + "\""); System.out.println("selection is: \"" + textf.getSelectedText( ) + "\""); return true; } return super.action(e,arg); } (class Experiment to be continued) CS100A, Lecture 16, 27 October 1998 13 // Process press of WINDOW_DESTROY or mouse up // in a CheckersSquare public boolean handleEvent(Event e) { //System.out.println("" + e); if (e.id == Event.WINDOW_DESTROY) { System.out.println("Window destroy clicked"); //dispose(); return true; } if (e.id == Event.MOUSE_UP && e.target instanceof CheckersSquare) { System.out.println("Mouse up in a” + “CheckersSquare"); return true; } if (e.id == Event.MOUSE_MOVE) { System.out.println("Mouse move"); return true; } return super.handleEvent(e); } } (End of class Experiment) CS100A, Lecture 16, 27 October 1998 14 public class TrivialApplication { public static void main(String args[]) { System.out.println( "Hello World!" ); Experiment f= new Experiment(); } // A square of the game Checkers public class CheckersSquare extends Canvas { static public final int EMPTY= 0; static public final int RED= 1; static public final int BLACK= 2; Rectangle b; // Containing rectangle of this square int col; int row;// col, row no. of this square on board private int fill= EMPTY; // Constructor: An initially empty square that belongs in // column c, row r of the board public CheckersSquare(int c, int r) { super(); col= c; row= r; if ((c+r)%2 == 1) setBackground(color.gray); else setBackground(color.pink); resize(42,42); b= bounds(); repaint();} (to be continued) CS100A, Lecture 16, 27 October 1998 15 (continuation of CheckersSquare) // Constructor: An initially empty square that belongs in // column c, row r of the board public CheckersSquare(int c, int r) { super(); col= c; row= r; if ((c+r)%2 == 1) setBackground(color.gray); else setBackground(color.pink); resize(42,42); b= bounds(); repaint(); } // Paint square (with its piece, if any), using Graphics g public void paint (Graphics g) { Color save= g.getColor( ); if (fill==RED) g.setColor(Color.red); else g.setColor(Color.black); g.fillOval(b.x+b.width/5, b.y+b.width/5, b.width/2, b.height/2); g.setColor(save); } } (end of class CheckersSquare) CS100A, Lecture 16, 27 October 1998 16 EVENTS Event: something like mouse down, mouse drag, click on a button, pressing a key down, letting a key up, and clicking on the “window-destroy” box. An event represented by an instance of class Event. Java 1.0 event handling is different from Java 1.1 event handling. We discuss Java 1.0 event handling. When an event happens, one of two methods is called: // Handle button click --return “click processed” public boolean action(Event e, Object arg) {Similar to body of handleEvent} // Handle all other events --return “event handled” public boolean handleEvent(Event e) { if (event can be handled) { Process event; return true; } return super.handleEvent(e); } CS100A, Lecture 16, 27 October 1998 17 The game of checkers To play the game using a finished program, execute the applet on the CS100A home page (look for assignment 7). For this assignment, download files as instructed on the handout for the assignment. You get a copy of the completed program with parts removed, and you have to fill them in. You will not have to write code that manipulates the GUI, but you are encouraged to study the GUI code! Class Checkers is a subclass of Frame, so an instance is a window on the monitor. Class CheckersSquare is a subclass of Canvas, so an instance is a component on which one can draw ovals and such. An 8x8 array of elements of Class CheckersSquare forms the checker board. Class IntLabel is used to encode two different representations of a number: Int and Label. CS100A, Lecture 16, 27 October 1998 18 Class CheckersSquare Each square of the checkerboard is an instance of CheckersSquare. Field fill is the piece on this square Fields row, col contain the square’s row, col number Field toBeMoved: = “The piece should be highlighted” Method paint is called by the system whenever the square should be repainted. Repainging can also be requested by a method of this class by calling method repaint. Class CheckersSquare contains a bunch of methods that you should use in writing your code. Spend several minutes familiarizing yourself with them before doing any coding. CS100A, Lecture 16, 27 October 1998 19 Class Checkers Fields for checker game (not GUI) // Number of red pieces and black pieces on the board IntLabel redCount= new IntLabel(0, reds); IntLabel blackCount= new IntLabel(0, blacks); // clickflag describes clicks made by the user // = 0: No piece has been chosen (clicked on). For all // squares, field toBeMoved is false. // = 1: click was made on a piece of color colorToPlay // oldSq is the square of the piece to be moved; it’s // the only highlighted square int clickflag = 0; CheckersSquare oldSq; int colorToPlay; // player (i.e. color) to place next int otherColor; // the other color Your changes are restricted to five methods, but before you make the changes, study carefully at all the other methods in class Checkers. // Set the board up for a new game public void newGame( ) CS100A, Lecture 16, 27 October 1998 20 // Move piece from oldSq to newSq and return true. If // move is not possible, do nothing and return false. private boolean validMove(CheckersSquare oldSq, CheckersSquare newSq) // Return "move oldSq to newSq is valid non-jump // move for player colorToPlay". Assume oldSq contains // a piece of colorToPlay and newSq is empty black square private boolean isValidNonjump(CheckersSquare oldSq, CheckersSquare newSq) // Return "move oldSq to newSq is valid jump for player // colorToPlay". Assume oldSq contains piece and that // newSq is an empty black square private boolean isValidjump(CheckersSquare oldSq, CheckersSquare newSq) // clickflag=1. If pieces on oldSq and newSq have same // color, switch to moving the piece on newSq. Otherwise // try to move piece from oldSq to square newSq. If not // possible, give error message; if possible, do it and // switch players public void processClickTwo(CheckersSquare newSq) CS100A, Lecture 16, 27 October 1998 21