תוכנית הדגמה
תוכנית ההדגמה לשיעור זה מוצגת להלן. מידע רב אודות תוכנית זו קיים בהערות המופיעות בהתחלה.
כל אחד מהחלקים של המתודה handleEvent() נידון באופן מקיף לאחר פירוט התוכנית.
/*File Event03.java Copyright 1997, R.G.Baldwin are displayed. is detected, which causes an ACTION_EVENT object to be created and delivered to the Button by using the deliverEvent() method. The result is the handled in an ideal manner in order to preserve simplicity. In particular, if the first thing that you do is to press the b or B key, nothing happens. //save coordinates for display here //used to instantiate a TextField object //than before we will to use a constructor to build it. //add it to the bottom of the frame //instantiate obj of this type // user clicks (evObj.target == this)){ //clear the counter and modify text in the TextField This textField is not editable."); // it to the button if the "Dummy string"); // could use postEvent() instead of deliverEvent() // (or a program-generated // action event is delivered to the button) // increment the counter which (evObj.target == myButton)){ This textField is not editable."); // in the superclass // This displays graphic coordinate information in // the blank area of the frame.
Primarily designed to illustrates program-generated events.
A frame contains a Button and a TextField. When the user
clicks the Button, a counter is incremented and displayed
in the TextField.
If the user clicks in the blank area of the frame, the counter
is reset and the coordinates of the mouse pointer
If the user presses the b or B keys, a KEY_PRESS event
same as if the Button had been clicked.
This is a program-generated event.
Closing the frame terminates the program.
Note that there are some focus issues that are not
*/
import java.awt.*;
//Make the controlling class extend the Frame class
// to produce a graphic window that can accept events.
public class Event03 extends Frame{
String msg = ""; //save message for display here
int clickX = 0, clickY = 0;
Button myButton; //used to instantiate a button object
TextField myTextField;
int counter = 0;
//Because this display is a little more complicated
public Event03(){//constructor
//put a button at the top of the frame
myButton = new Button("Click Here to Increment Counter");
add("North", myButton);//add it to the top of the frame
//put a non-editable TextField at the bottom of the frame
myTextField = new TextField(
"counter = " + counter + "
This textField is not editable.");
add ("South",myTextField);
myTextField.setEditable(false);//make it non-editable
//Dress the frame up a little
setTitle("Copyright 1997, R.G.Baldwin");
resize(300,200);//set frame size
}//end constructor
//Create and display the frame
public static void main(String[] args){
Event03 displayWindow = new Event03();
displayWindow.show();//display the frame
}//end main
//Override handleEvent() method in Component class
// to process all events.
public boolean handleEvent(Event evObj){
//Terminate program if user closes the window
if(evObj.id == Event.WINDOW_DESTROY) System.exit(0);
//Display the coordinates and clear the counter when
// in blank portion of the frame.
if( (evObj.id == Event.MOUSE_DOWN) &&
clickX = evObj.x; //save mouse coordinates
clickY = evObj.y;
//construct message for display
msg = "" + clickX + ", " + clickY + ", Clear counter";
counter = -1;
myTextField.setText(
"counter = " + ++counter + "
repaint(); //force a repaint of the window
}//end if on MOUSE_DOWN in blank portion of frame
//Create an action event object and deliver
// user presses b or B.
if( (evObj.id == Event.KEY_PRESS)
&& ((evObj.key == 'b') || (evObj.key == 'B')) ){
Event event = new Event(myButton,Event.ACTION_EVENT,
deliverEvent(event);
//postEvent(event);
}//end if on KEY_PRESS
//When the user clicks the button,
// uses the textField as a display device.
if( (evObj.id == Event.ACTION_EVENT) &&
myTextField.setText(
"counter = " + ++counter + "
}//end if on ACTION_EVENT
//Always finish by invoking the handleEvent method
// to handle any events not handled above.
return super.handleEvent(evObj);
}//end handleEvent()
//Override paint method to repaint the window.
public void paint(Graphics g){
g.drawString(msg, clickX, clickY);
}//end paint()
ראשית, היינו זקוקים ליותרGUI בתוכנית זו מאשר בתוכניות אחרות כדי שיהיו לנו מספיק כלים זמינים להדגים את התפיסה של "אירועים הנוצרים על-ידי תוכנית". בנוסף לאובייקט ה- Frame שבו השתמשנו בתוכניות קודמות , היינו זקוקים גם לרכיב Button ולרכיב TextField.
ה- Button משמש לקידום מונה בכל פעם שלוחצים עליו.
ה- Textfield משמש להצגת ערך המונה.
לעת עתה, אתה מתבקש לקבל את העובדה שהקוד בפונקציה הבונה יפיק את ממשק המשתמש הרצוי.
אנו נדון בהרחבה בסוגיות הנוגעות ליצירת ממשקי משתמש באמצעות רכיבים בחלק מהשיעורים הבאים.
הקוד שלמעשה מעניין אותנו כאן הוא:
- המתודה ()handleEvent הדרוסה, ובאופן יותר ספציפי
- החלק של המתודה הדרוסה שיוצר ושולח אירוע פעולה ל-Button .
הבה נבחן את המתודה הדרוסה handleEvent() בהתאם לכל אחד מהחלקים.
נדלג על החלק שמגיב לאירועWINDOW_DESTROY כדי לסיים את התוכנית. כבר ראית זאת בעבר ולא ערכנו כל שינוי משמעותי בתחום זה.
הצגת הקואורדינטות של העכבר ואיפוס המונה
עיין תחילה בחלק זה של המתודה המציג את קואורדינטות העכבר ומאפס את המונה כאשר המשתמש לוחץ בחלק הריק של ה-Frame.
|
קוד זה מתחיל בכניסה אל אובייקט ה- Event ובאישור ההתרחשות של אירוע MOUSE_DOWN באובייקט ה- Frame (המיוצג על-ידי this).
לאחר מכן, בדומה לתוכניות הדגמה אחרות, הקוד מגדיר מידע מסוים כך שיוצג על-ידי המתודה paint() בעת הפעלתה, או על-ידי קריאה ל- repaint() או בגלל פעילות מערכת כלשהי כמו למשל שחזור התצוגה כאשר המשתמש מזיז דברים ממקום למקום. ראית זאת בעבר.
לאחר מכן מפעיל הקוד מספר הוראות פשוטות למדי כדי לאפס את המשתנה של המונה ומציג את הערך שלו.
לאחר מכן הוא קורא ל- repaint() כדי שתכפה על הגרפיקה של התצוגה להיצבע מחדש.
מלבד העובדה שכל זה היה כלול בתוך המתודה הדרוסה handleEvent() במקום השימוש במתודת "נוחיות", אין כאן קושי מיוחד.
יצירת אירוע פעולה (Action Event) ושליחתו אל הלחצן
זהו החלק החשוב ביותר של כל השיעור הזה (וכל זה קורה בשלוש שורות של קוד).
הקוד שלהלן ייצור אובייקט Event מטיפוס ACTION_EVENT וישלח אותו לאובייקט ה- Button לשם עיבוד.
האירוע נוצר ונשלח בכל פעם שהמשתמש מקיש על המקש “b” או “B” שבלוח המקשים.
התוצאה הסופית של ההקשה על אחד מן המקשים האלה זהה ללחיצה על הלחצן באמצעות העכבר.
if( (evObj.id == Event.KEY_PRESS)
&& ((evObj.key == 'b') || (evObj.key == 'B')) ){
Event event = new
Event(myButton,Event.ACTION_EVENT,"Dummy string");
deliverEvent(event);
//postEvent(event);
// could use postEvent() instead of deliverEvent()
}//end if on KEY_PRESS
כפי שתוכל לראות, הקוד הדרוש ליצירת אירוע הנוצר על-ידי תוכנית הוא פשוט להפליא.
מקטע קוד זה מתחיל בתגובה לאירוע מטיפוס KEY_PRESS ובאישור העובדה שהוא היה תוצאה של הקשה על מקש האות “B” הקטנה או הגדולה. אם לא התקיימו שני התנאים הנ"ל,
מקטע הקוד מתעלם מהאירוע ומשאיר ל- handleEvent() להתמודד אתו מאוחר יותר.
אם שני התנאים הנ"ל מתקיימים, מקטע הקוד יוצר מופע לאובייקט חדש מטיפוס Event כש-
· ה target מצוין כמשתנה ההתייחסות המצביע על הלחצן הספציפי בו מעונינים ו-
·ה- id מצוין כאירוע מטיפוס ACTION_EVENT.
כותב התוכנית ידע מראש שמטפל באירועים של אירוע הפעולה בלחצן יתעלם מהפרמטר השלישי, לכן הוא פשוט הועבר פנימה כמחרוזת "דמה".
מקטע הקוד מפעיל את המתודה deliverEvent() כדי לגרום למערכת לשלוח את אובייקט ה- Event החדש לאובייקט ה- Button.
זה גורם לתוכנית להתנהג כאילו אובייקט ה- Button קיבל ACTION_EVENT באופן ישיר (כמו לדוגמה לחיצה של המשתמש עליו). כפי שנאמר קודם, ניתן היה גם להשתמש במתודה postEvent() למטרה זו, אולם אני משאיר לסטודנט כתרגיל את המשימה לגלות את הדברים הדומים, השונים והקשר בין שתי המתודות האלה.
עיבוד של אירוע פעולה בלחצן
כאשר המשתמש לוחץ על הלחצן (או כאשר אירוע פעולה הנוצר על-ידי תוכנית נשלח ללחצן) מקטע הקוד הבא יקדם את משתנה המונה ויציג את הערך של המונה ב- textField.
if((evObj.id==Event.ACTION_EVENT)&&
evObj.target==myButton)){
myTextField.setText(
"counter = " + ++counter +
"This textField is not editable.");
}//end if on ACTION_EVENT
אין הרבה מה לומר על קוד זה. הוא פשוט מאשר כי זהACTION_EVENT וכי אובייקט ה-Button הספציפי הוא המטרה (target), ולאחר מכן מקדם את משתנה המונה ומציג אותו.
Wrapup, טיפול באירועים בלתי מטופלים (Unhandled Events)
בכל פעם שאתה דורס את המתודה handleEvent(), עליך לטפל באופן ספציפי בכל האירועים האפשריים ( שזו כנראה לא אפשרות מעשית) או להפעיל את המתודה handleEvent() ברמה אחת גבוהה יותר כך שהיא תוכל להתמודד עם כל אירוע שלא טיפלת בו באופן ספציפי. ניתן לעשות זאת באופן הבא:
//Always finish by invoking the handleEvent method
//in the superclass
// to handle any events not handled above.
return super.handleEvent(evObj);
//end handleEvent()