Advanced Computer Programming Inf1BOb ject-Oriented Programming LAB 07 (week 8) - Widgets OOP Lab Exercise 3 (week 5) – Widgets Hutchins 19th January 2007 7th-9th February, 2006 1 Introduction 1, In OOP assignment 2, you will learn how to implement a simple class hierarchy — a hierarchy of shapes. This lab introduces a similar concept, called a widget . So what is a widget? You see them every time you turn on a computer. Widgets are the building blocks that make up a graphical user interface , or GUI, which is the part of the application that you see on the screen and interact with. Buttons, check boxes, menus, scroll bars, sliders, text fields etc. are all widgets. As a general rule of thumb, if you can see it on the screen, or click on it with your mouse, it’s a widget. Widgets are interesting for two reasons. First of all, if you want to write a program with a GUI, then you have to learn how to use them. Second, the invention of object- oriented programming itself was motivated in part by the need to deal with widgets. Classes, inheritance, and class hierarchies have proved to be very useful mechanisms for organizing GUI libraries, and they are thus an excellent illustration of the benefits of object-oriented programming. Unfortunately, a modern widget library such as that supplied by Java is immensely complicated, and difficult even for experienced programmers to master. We will not be teaching the Java libraries in any detail in this course. Instead, we will provide you this course. with a much smaller, simpler library, which was specially developed for Informatics 1B. 1.1 Events Like shapes, each widget has a size and position on the screen. Each kind of widget is also responsible for drawing itself in an appropriate way — e.g. buttons draw text surrounded by a box, while scroll bars draw a rectangle with arrows. Most importantly, widgets respond to events . Every time the user moves the mouse, clicks on something, or presses a key, it generates an event . The Java libraries will process that event, and then call a method of the appropriate widget. When you click on a button, the button object receives a mouseClicked event. When you drag a scrollbar up and down, the scrollbar object receives a series of mouseDragged events. The Widget class defines a number of methods for handling events. In this lab, you will make a new kind of widget by creating a class which inherits from Widget , and then overrides these methods. The methods that you will override are described below. 1
• draw(g) is called whenever the widget needs to be drawn. A widget may need to be drawn whenever a window appears, is uncovered, or is resized. A widget may also need to be re-drawn if the picture that it’s showing changes in some way; the redraw() command will force a widget to be drawn again. • mouseMoved(x, y) is called whenever the mouse cursor moves within the widget. The x and y arguments specify the location of the mouse cursor. • mouseClicked(x, y, button, nclicks) is called whenever the mouse is clicked within the widget. – x and y specify the location of the mouse. – button specifies which button was clicked: 1 for the left, 2 for the middle, and 3 for the right. – nclicks is 1 for a single click and 2 for a double click. • mouseDragged(x, y) is called whenever the mouse cursor moves within the widget while one of the buttons is depressed. 1.2 Smiley Faces A SmileyFace is a shape that consists of two eyeballs and a smile. Shapes the are the subject of OO assignment 2, but you don’t need to worry about that now. The SmileyFace class defines the following methods: • new SmileyFace(x,y,r) will create a new smiley face at position ( x, y ). The radius of an eyeball is given by r . • draw(g) will draw the smiley face. • inside(x,y) will return true if the point ( x, y ) is inside the face. • move(dx,dy) will move the face by the offset ( dx, dy ). If the shape was at position ( x 0 , y 0 ) before calling draw() , it will be at position ( x 0 + dx, y 0 + dy ) afterward. • getRadius() and setRadius() will get and set the radius of the eyeball, which controls the size of the whole face. • lookAt(x,y) will cause the eyes to focus on the point ( x, y ). Unlike widgets, shapes do not handle events or draw themselves automatically. 1.3 Downloading the Example Code Do the following: You can download the example code for the lab from: (1) Download the Smiley.zip file and unzip the file to a local directory "lab07" http://www.inf.ed.ac.uk/teaching/courses/inf1/oop/labs/Smiley.zip (2) Create a project named "Smiley" in NetBeans - Project > Project Manager > New Create a new project named “Smiley”, and import the code from the .zip file as - Right click on "Filesystems" and choose Mount > Lolal Directory > lab07 normal. You will also need to create a run profile named “Smiley”, with “SmileyMain” (3) Compile & Execute the project. When you execute the project, set Project Main as the main class. Class to "SmileyMain". 2 Making a smiling face The example code will open a new window, and create a single widget: an instance of SmileyCanvas . SmileyCanvas is a simple widget which provides a home in which smi- ley faces can live. The first thing you need to do for this lab is put a SmileyFace onto the canvas. Go to the file SmileyCanvas.java , and make the following modifications: 2
• Add a new field named smiley of type SmileyFace . • In the constructor, initialize smiley to new SmileyFace(0, 0, 3) . • Change the draw(g) method so that it calls smiley.draw(g) . Now run the program. You should see a smiley face! 3 Breathing some life into it. Now we’ll make the face a bit more attentive. • Implement the mouseMoved(x,y) method so that the eyes of smiley track the mouse cursor. ( Hint: use the lookAt method.) • After changing the face, use the redraw() command to force the widget to redraw itself. Now run the program. The eyes should follow the mouse cursor, as shown in the following screenshot: 4 Moving the face Your next task is to make it possible to move the face by dragging it. The move(dx, dy) method will move the face, but dx and dy are offsets , not coordinates. In other words, the move command will slide the face in a particular direction; it will not move it to a particular location. You should implement mouseDragged(x,y) to move the face. Since x and y specify a location, not an offset, you must calculate the offset by comparing the current position of the mouse with the previous position of the mouse. Do the following: • Add two new fields named mouseX and mouseY , of type double . • Modify mouseMoved() so that it sets these two variables to the current position of the mouse. 3
• Implement mouseDragged(x, y) so that it does three things: – Moves the face by the proper offset, which is (x-mouseX, y-mouseY) . – Set mouseX and mouseY to the new position of the mouse. – Call redraw() . You should now be able to drag the face around in the window. 5 Big and small faces. Now that you have a properly attentive face, you need to provide a way to make it bigger or smaller. Ordinarily, you might add some buttons labeled “zoom in” and “zoom out”, but adding buttons means dealing with multiple widgets, and that makes things a little more complicated than necessary for our purposes. Instead, we’ll just use mouse clicks to control the face. • Implement the mouseClicked() method so that: – The radius of the face increases by a factor of 0.9 when the user clicks the left mouse button. – The radius decreases by 1.1 when the user clicks the right mouse button. • Call redraw() after changing the face. Now run the program. Does the face get bigger and smaller? 6 Multiple Faces Now that you can move and resize faces, the next logical step is to put many faces onto the same canvas. Instead of storing a single face, we will store an array of faces. Unlike lists, arrays can only store a fixed number of items, and that makes it hard to add or remove faces while the program is running. So instead of trying to change the size of the array, we will simple pre-allocate an array that is big enough to hold as many faces as we are likely to need. 10 faces is sufficient for this lab. The array will be initialized at first to hold null values. Each time a new face is added, it is stored in the next available slot in the array. We also need to keep track of the number of faces that are actually stored in the array, both because we need to know where the next available slot is, and because we need to make sure not to put more than 10 faces in the array. The following diagram illustrates how the array works. To handle arrays, you must add the following fields and methods to the class: 4
Recommend
More recommend