» נושאי לימוד
» נושאי לימוד
יום רביעי 24 באפריל 2024
טיפול באירועים ב-JDK 1.0.2, רכיבים חכמים
דף ראשי  מתקדמים  טיפול באירועים ב-JDK 1.0.2, רכיבים חכמים גרסה להדפסה
 

טיפול באירועים ב-JDK 1.0.2  , רכיבים חכמים

- מבוא

- מערכת זמן ריצה

- יצירת רכיבים חכמים

- תוכנית דוגמא

- תשובה לשאלה המקורית


מבוא

 

גירסת בטא של JDK 1.1  זמינה כעת לבדיקה , ו-SUN הכריזו שהיא תכלול שינויים חשובים ל- Abstract Windows Toolkit, כולל שינויים ליישום אירועים וטיפול באירועים.

 

כששאר JDK 1.1  יצא לאור ומידע אמיתי בנוגע לשינויים אלה יהיה זמין, שיעור זה יתוגבר על ידי שיעור חדש המתאר אירועים וטיפול באירועים תחת JDK 1.1.

 

רוב פעולות המשתמש הקשורות לרכיב GUI כנראה מטופלות על ידי רכיב המכל.

 

מבין סיבות נוספות, זהו המקום בו ניתן לבטל את פונקציות טיפול באירועים של מחלקת הרכיב על מנת לספק תפקוד רצוי.

 

אם נרצה רכיב שיהיה מסוגל לטפל באירועים של עצמו (בניגוד לטיפול על ידי מכל) נוכל להרחיב את המחלקה של אותו רכיב, ועל ידי כך יצירת מחלקה עבור רכיב מותאם (custom components) בעל כל תכונות הרכיב המקורי.

 

כך, במקום הוספת אובייקט מסוג הרכיב המקורי למיכל שלנו, אנו מאתחלים ומוסיפים אובייקט מהסוג המותאם החדש.

 

אחרי שעשינו זאת, נוכל לכתוב מנהלי אירועים (event handlers) עבור מחלקת הרכיב הנהוג על מנת לטפל באירועים ברמת הרכיב ולא ברמת המכל.

 

אובייקטים של אירועים המגיעים ממערכת  זמן ריצה

( (Event Objects Come from the Runtime System

 

הדברים הבאים הם הבנתי הכללית של חיבור הכל יחד ב-  JDK 1.0.2 נכון לפברואר 1997.

הבנה זו מבוססת על קריאה בין השורות  של כמות גדולה של ספרים, ספציפיקציות ומאמרים.

 

כפי שאתה עשוי לזכור, פעולת משתמש המעורבת עם רכיב GUI גורמת למערכת ההפעלה לשלוח הודעה למערכת  זמן ריצה של Java.

 

מערכת  זמן ריצה

 

-  מפרשת את ההודעה, מוציאה את המידע הטמון בה,

-  סוגרת בתוכה מידע זה לתוך אובייקט מסוג typeEvent

-  קוראת לפונקצית ה- postEvent() עבור הרכיב, ומעבירה את האובייקט כפרמטר.

 

אחד מתפקידי פונקצית ה- postEvent() הוא לטפל במשימה של העברת אובייקט ה-Event במעלה היררכית הרכיבים עד שפונקצית ה-handleEvent ברמה מסוימת מחזירה אמת המציין שהאירוע טופל.

 

 ברירת המחדל של פונקצית ה- handleEvent() עבור הרכיב כנראה מחזירה שקר, המאותת לפונקצית ה- postMethod() לקרוא לפונקצית ה- handleMethod() עבור מיכל הרכיב.

ברמת המיכל, ולא ברמת הרכיב, האירוע בדרך כלל מנוהל.

 (הרבה אירועים אקראיים לא מנוהלים, אלא מופצים למעלה עד שהם נזנחים).

 

סביר להניח, שתעצב את המחלקה עבור המיכל. על ידי כך תוכל לבטל את פונקצית ה-handleEvent על מנת

-   להוציא את המידע הטמון באובייקט

-   ליישם את התפקיד הרצוי עבור אירועים אלה בהם אתה מתעניין.

 

בנוסף ישנם מספר פונקציות טיפול-אירועים נוחות שתוכל לבטל, ולהשתמש בפונקצית handleEvent() אם אתה מעדיף.

 

קרוב לוודאי שתנהל אירועים בהם אתה מתעניין, ותחזיר שקר עבור אותם אירועים שאינם מעניינים אותך, שוב תוך איתות לפונקצית ה- postEvent() להעביר את האירוע למיכל ברמה הגבוהה יותר בהיררכיה.

 

 

 

יצירת רכיבים חכמים Creating Smart Components))

 

אם אנחנו

-  מרחיבים את מחלקת הרכיב המעניין,

-  מאתחלים אובייקט של מחלקה חדשה זו,

-  מוסיפים אותו למיכל שלנו,

 

נוכל לבטל את פונקצית ה- handleMethod() (ואם יש צורך, את פונקצית ה- postMethod) עבור מחלקה זו וזה מעניק לנו את היכולת לטפל באירועים ברמת הרכיב (או הרכיב המותאם).

 

קושי אחד במעשה הוא קביעה מראש האם מערכת ה-  זמן ריצה תייצר אובייקט Event ותקרא לפונקצית ה- postMethod() על הרכיב הנהוג עבור פעולת משתמש ספציפית.

 

התיעוד הוא שטחי, ורוב הספרים שפורסמו לאחרונה מדלגים של הנושא.

 

על מנת לתת לנו דוגמה קונקרטית לעבוד אתה, בואו נשקול את השאלה הבאה:

- האם מערכת זמן  הריצה יוצרת ומעבירה הלאה אובייקטים מסוג Event  כאשר העכבר נכנס לשדה טקסט (TextField) או מקיש בשדה טקסט? והאם היא יוצרת ומעבירה אובייקט Event בכל פעם ששדה טקסט מקבל את המיקוד?

 

זוהי אינה שאלה שניתן לענות עליה בקלות. רוב הספרים הקיימים פשוט מתעלמים מעניינים טכניים ברמה זו.

 

נכון לפברואר 1997, אני בדעה ש- Java in a Nutshell של David Flanagan

הוא אחד מספרי ה- Java הטובים והאינפורמטיביים הקיימים.

 

בעמוד 183, תוך דיון בתרשים המופיע בטקסט שלו, Flanagan מציין:

-      "אירועים הרשומים עבור סוג רכיב Component חלים על כל תת המחלקות
        
Component
של java.awt.

 

אני מאמין שהוא אומר שכל רכיב אשר מורש ממחלקת Component, בצורה ישירה או עקיפה, יקבל את כל סוגי האירועים שהוא רושם תחת Component.

 

רשימת התרשימים

-  MOUSE_ENTER – כניסת עכבר

-  MOUSE_EXIT - יציאת עכבר

-  MOUSE_DOWN – לחיצת עכבר

-  MOUSE_UP – עזיבת עכבר

-  MOUSE MOVE – תזוזת עכבר

-  MOUSE_DRAG – גרירת עכבר

 

תחת Components (בנוסף לסוגי אירועים אחרים, הכוללים GOT_FOCUS).

 

מכיוון שמחלקת TextField מרחיבה את מחלקת TextComponent אשר מרחיבה את מחלקת Component, ניתן להאמין כי אובייקט TextField מקבל את כל אירועי העכבר הרשומים לעיל בנוסף לאירוע GOT_FOCUS.

 

אבל, זהו לא המקרה כפי שנראה מאוחר יותר בתוכנית הדוגמא.

 

כאשר לוחצים על עכבר באובייקט TextField (אשר מערב את כל אירועי העכבר הרשומים לעיל מלבד MOUSE_DRAG) אובייקט ה- TextField מקבל את המיקוד,

כפי שהוכח על ידי סמן ה I-beam המהבהב.

כתוצאה,  ייתכן ונצפה שהאובייקט יקבל סדרה של אירועי עכבר בנוסף לאירוע GOT_FOCUS.

 

תוכנית הדוגמא בשיעור זה משיגה שתי מטרות:

 

תחילה - היא מלמדת אותך ליצר רכיבים חכמים אשר יכולים להגיב לאירועים אשר הוצבו על ידי מערכת זמן הריצה עבור רכיבים אלו.

שנית - היא מלמדת אותך לרשום תוכנה פשוטה בעזרתה תוכל לקבוע באופן ניסויי אם מערכת  זמן הריצה מציבה או לא מציבה אובייקט Event עבור פעולת משתמש ספציפית לגבי אובייקט GUI ספציפי בעל עניין.

 

נשתמש בתוכנית הדוגמא בניסיון לענות על השאלה שהוצגה לעיל.

ננסה ללמוד מספר דברים מעניינם אחרים בנוסף.

 

תוכנית דוגמא (Sample Program)

 

תוכנית דוגמא עבור שיעור זה מתוארת להלן. ישנו דיון מפורט אחרי רישום התוכנה. הדיון כולל תוצאות ניסוייות שהושגו עבור מספר פעולות משתמש ספציפיות שעירבו אובייקט TextField נהוג אשר יצרו והשתמשו בו בתוך התוכנה.

 


 

/*File Event05.java Copyright 1997, R.G.Baldwin

Primarily designed to illustrate smart components, and a method for
determining the events received by a component.

Closing the frame terminates the program.
*/

import java.awt.*;

//Define a custom TextField class that can respond to events.
// Note that this class extends TextField.
class TF extends TextField{
TF(String inString){setText(inString);}//end constructor

//The following event handler method handles events at the
// component level as opposed to the container level.
public boolean handleEvent(Event evObj){
System.out.println(evObj.toString());//display the Event object

switch(evObj.id){//display type of event
case Event.KEY_PRESS :
setText(getText() + "," + "KEY_PRESS");break;
case Event.KEY_RELEASE :
setText(getText() + "," + "KEY_RELEASE");break;
case Event.ACTION_EVENT :
setText(getText() + "," + "ACTION_EVENT");break;
default : //catch and display all other event types here
setText(getText() + "," + evObj.id);
}//end switch
return super.handleEvent(evObj);
}//end handleEvent() in class TF

}//end class TF
//===================================================================

//Make the controlling class extend the Frame class to provide
// a container for the custom TextField component
public class Event05 extends Frame{

public Event05(){//constructor
TF myTextField = new TF("TF");//instantiate custom TextField object
add ("Center",myTextField);//add it to the frame
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 show the frame object
public static void main(String[] args){
Event05 displayWindow = new Event05(); //instantiate obj of this type
displayWindow.show();//display the frame
}//end main

//Override handleEvent() method relative to the frame for program termination
public boolean handleEvent(Event evObj){
//Terminate program if user closes the window
if(evObj.id == Event.WINDOW_DESTROY) System.exit(0);
//Always finish by invoking the handleEvent method in the superclass
return super.handleEvent(evObj); &nb
1000
sp;
}//end handleEvent()

}//end class Event05


 

בתוכנה זו, רכיב חכם בצורת שדה טקסט נהוג הוגדר על ידי הרחבת מחלקת ה- TextField. אובייקט מסוג זה אותחל והוצב במסגרת ההופכת להיות המכל עבור הרכיב.

 

מכיוון שהגדרת המחלקה עבור רכיב נהוג כוללת גרסה מבוטלת של handleEvent(), לרכיב נהוג זה יש את היכולת לטפל באירועים של עצמו ולא להעבירם הלאה למכל המסגרת לעיבוד.

 

עקב הדוגמא של פונקצית ה- handleEvent() המבוטלת, נקישה על אובייקט ה-  TextField הנהוג על מנת לתת לו מיקוד בזמן הרצה ואז לחיצה על מקש מציגים מידע בשדה טקסט וגם מציגים מידע על מסך הלוח הבקרה.

 

יש חזרה על פונקצית ה-handleEvent המבוטלת לעיון נוח יותר.


 

  public boolean handleEvent(Event evObj){
System.out.println(evObj.toString());//display the Event object

switch(evObj.id){//display type of event
case Event.KEY_PRESS :
setText(getText() + "," + "KEY_PRESS");break;
case Event.KEY_RELEASE :
setText(getText() + "," + "KEY_RELEASE");break;
case Event.ACTION_EVENT :
setText(getText() + "," + "ACTION_EVENT");break;
default : //catch and display all other event types here
setText(getText() + "," + evObj.id);
}//end switch
return super.handleEvent(evObj);
}//end handleEvent() in class TF

 

 

 

כפי שניתן לראות, המידע המוצג על מסך לוח הבקרה הוא המרת ה-toString() של אובייקט ה- Event אשר נשלח על ידי מערכת זמן ההרצה לפונקצית ה- postEvent()  ולבסוף לפונקצית ה- handleEvent().

 

לדוגמא, לחיצה על מקש return כאשר אובייקט ה- TextField הוא בעל המיקוד גורמת למידע הבא להופיע על לוח הבקרה (רק החלק ההתחלתי של כל שורה מופיעה):

 

java.awt.Event[id=401,x=0,y=0,key=10,target=TF[4,175,292x21,text=TF,... java.awt.Event[id=1001,x=0,y=0,target=TF[4,175,292x21,text=TF,... java.awt.Event[id=402,x=0,y=0,key=10,target=TF[4,175,292x21,text=TF,...


The integer values
 

id = 401, 1001, and 402

 

 

בפלט שלעיל הם בהתאמה ערכי שדות id  עבור:

-   KEY_PRESS

-   ACTION_EVENT

-   KEY_RELEASE

 

לחיצה על מקש return(אנטר) כאשר אובייקט ה- Text Field הוא בעל המיקוד גורמת בנוסף לאובייקט ה-Event להיות מפורש על ידי פונקצית ה- () handleMethod ולהיות מוצג בשדה הטקסט.

 

המידע הבא מוצג בשדה הטקט כאשר לוחצים על מקש ה- return.

 

שים לב, שה- TF ממוקם בהתחלה כאשר אובייקט ה- TextField מאותחל.

הטקס הנוסף ממוקם שם על ידי קוד בפונקצית ה- handleEvent() כאשר כל אירוע נוסף פשוט מוסיף עוד טקסט  למחרוזת הטקסט הקיימת.

 

TF,KEY_PRESS,ACTION_EVENT,KEY_RELEASE

 

במילים אחרות, לחיצה על מקש return פעם אחת גורמת לשלושה אובייקטים של Event  נפרדים להיות מועברים לפונקצית handleEvent() עבור אובייקט TextField  הנהוג:

-   אירוע אחד מועבר כאשר המקש נלחץ

-   אירוע נוסף מועבר כאשר המקש משוחרר

- אירוע נוסף מועבר בין שני אלה על מנת לציין ש- ACTION_EVENT   אירע.

 

כדוגמא נוספת, לחיצה על מקש לאות "A" מציגים את הדברים הבאים על לוח הבקרה:

 

java.awt.Event[id=401,x=0,y=0,key=97,target=TF[4,23,292x173,text=TF,... java.awt.Event[id=402,x=0,y=0,key=97,target=TF[4,23,292x173,text=TF,...

 

וגורמת לדברים הבאים להיות מוצגים בשדה הטקסט הנהוג.

TF,KEY_PRESS,KEY_RELEASE

במקרה זה, רק שני אירועים מועברים לפונקצית handleEvent():

-   אירוע אחד מועבר כאשר המקש נלחץ

-   אירוע שני מועבר כאשר המקש משוחרר.

 

כדוגמא אחרונה, לחיצה על המקש F1 מפיקה את הדברים הבאים על גבי לוח הבקרה:

 

java.awt.Event[id=403,x=0,y=0,key=1008,target=TF[4,23,292x173,text=TF,... java.awt.Event[id=404,x=0,y=0,key=1008,target=TF[4,23,292x173,text=TF,... 

 

והדברים הבאים מופקים בשדה הטקסט הנהוג:

TF,403,404

 

 

במקרה זה, 403 ו-404 הם בהתאמה ערכי אירוע של שדה ה- id  באובייקט Event  עבור

-  KEY_ACTION

-  KEY_CATION_RELEASE

 

משפט הבחירה (switch statement) בפונקצית ה- handleEvent() מאפשרת לערכים אלה ליפול תחת סעיף ברירת המחדל במקום בו הערך הנומרי של שדה ה- id ולא ייצוג סימבולי של האירוע הוצג.

 

התשובה לשאלה המקורית

 

השאלה המקורית הייתה:

-   האם מערכת הזמן ריצה יוצרת ומעבירה הלאה אובייקטים מסוג  Event כאשר העכבר נכנס לשדה טקסט (TextField) או מקליק (clicks) בשדה טקסט, והאם היא יוצרת ומעבירה אובייקט Event בכל פעם שדה טקסט מקבל את המיקוד?

 

באף מקרה אובייקטים של Event לא הועברו ל- postEvent() או ל- handleEvent() כתוצאה מפעולות עכבר באזור אובייקט ה- TextField  הנהוג.

 

כך שהשאלה לחלק הראשון של השאלה היא שכמסתבר מערכת זמן ההרצה לא יוצרת ומעבירה אובייקטים של Event כאשר העכבר נכנס לשדה טקסט או מבצע הקשה  בתוך שדה טקסט.

אובייקט TextField נראה חסין בפני אירועי עכבר.

 

קליק של העכבר על אובייקט TextField  מותאם נתן לו את המיקוד אך לא גרם לאירוע עם שדה id  המכיל  GOT_FOCUS  להיות מועבר לפונקציות postMethod() ן- handleMethod().

 

לכן, התשובה לחלק השני של השאלה היא שמערכת זמן הריצה אינה יוצרת או מעבירה אובייקט Event בכל פעם ששדה טקסט מקבל מיקוד.

 

כך, גרמנו לתוכנית הדוגמא שלנו לקבוע באופן ניסיוני את התשובה לשאלה המקורית.

 

ללא קשר לשאלה אך מעוררת עניין היא העובדה שחלק מהמקשים כדוגמת  CAPSLOCK, SHIFT, ו-Ctrl לא יצרו אירוע KEY_PRESS  ב- downstroke אך כן יצרו אירוע KEY_RELEASE  ב- upstroke.

 

מקש ה- Alt  לא יצר כל אירוע אלא אם כן מקש נוסף נלחץ כאשר מקש ה- Alt הוחזק למטה, ובמקרה זה רק יצר אירוע KEY_RELEASE ב- upstroke של מקש ה- Alt. במקרה זה, לחיצה על ושחרור של המקש השני בזמן החזקת מקש ה- Alt למטה לא יצר אירוע עצמאי מהאירוע שנוצר על ידי שחרור מקש ה- Alt.

 

תוצאות אלה הופקו תוך שימוש ב- Java JDK 1.0.2 הרץ תחת Windows 95.

 29-11-03 / 19:52  עודכן ,  13-10-03 / 17:36  נוצר ע"י רונית רייכמן  בתאריך 

 היררכית הטיפול האירועים ופונקצית ה-()postEvent - הקודםהבא -  AWT ו- Swing - הקדמה 
תגובות הקוראים    תגובות  -  0
דרכונט
מהי מערכת הדרכונט?
אינך מחובר, להתחברות:
דוא"ל
ססמא
נושאי לימוד
חיפוש  |  לא פועל
משלנו  |  לא פועל
גולשים מקוונים: 3