ג'אווה וטיפול באירועים

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

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

להיות מונע אירועים

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

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

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

שיעור האירועים

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

סוּג שֵׁם תיאור
לְהִתְנַגֵד יַעַד התייחסות לרכיב שקיבל בתחילה את האירוע.
ארוך מתי נקודת הזמן בה התרחש האירוע.
int תְעוּדַת זֶהוּת סוג האירוע (ראה סעיף סוגי אירועים למידע נוסף).
int איקס קואורדינטת x בה התרחשה הפעולה ביחס לרכיב שעובד כעת על האירוע. עבור אירוע נתון, הקואורדינטה x תשתנה בערכה ככל שהאירוע יעלה במעלה ההיררכיה של הרכיב. מקור מישור הקואורדינטות בפינה השמאלית העליונה של הרכיב.
int y קואורדינטת y בה התרחשה הפעולה ביחס לרכיב שעובד כעת על האירוע. עבור אירוע נתון, הקואורדינטה y תשתנה בערכה ככל שהאירוע יעלה בהיררכיית הרכיבים. מקור מישור הקואורדינטות בפינה השמאלית העליונה של הרכיב.
int מַפְתֵחַ עבור אירועי מקלדת, מקש המקש של המקש פשוט לחץ. הערך שלו יהיה בדרך כלל ערך ה- Unicode של התו שהמפתח מייצג. אפשרויות אחרות כוללות ערכים עבור המקשים המיוחדים HOME, END, F1, F2, וכן הלאה.
int משנים שילוב אריתמטי של ערכים SHIFT_MASK, CTRL_MASK, META_MASK ו- ALT_MASK. ערכו מייצג את מצב מקשי הסטה, השליטה, המטא והאלט בהתאמה.
int לחץ על ספירה מספר לחיצות העכבר העוקבות. חבר נתונים זה משמעותי רק באירועי MOUSE_DOWN.
לְהִתְנַגֵד טען ויכוח תלוי אירוע. עבור אובייקטים של לחצן, אובייקט זה הוא אובייקט מחרוזת המכיל את תווית הטקסטורה של הכפתור.
טבלה 1: חברי נתונים ציבוריים המסופקים על ידי אירוע הכיתה

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

סוגי אירועים

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

טבלה 2: אירועים המוגדרים על ידי ה- AWT, ממוינים לפי קטגוריות

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

אתה זקוק לדפדפן המותאם ל- Java כדי להציג יישומון זה

איור 1: יצירת אירועים בפעולה

משלוח אירועים והפצתו

שקול את היישומון באיור 2. הוא מורכב משני מופעים של מחלקת הלחצנים, המוטבעים במופע של מחלקת הפאנל. מופע זה של מחלקת הפנל מוטמע בעצמו בתוך מופע אחר של מחלקת הפאנל. המופע האחרון של מחלקת הפנל יושב מתחת למופע של הכיתה TextArea, ושני המופעים מוטבעים בתוך מופע של מחלקת היישומון. איור 3 מציג את האלמנטים המרכיבים יישומון זה המונח כעץ, כאשר מופעי TextArea ו- Button הם העלים, ומופע יישומון הוא השורש. (לקבלת מידע נוסף אודות הפריסה ההיררכית של רכיבים בממשק משתמש, קרא את מבוא ה- AWT בחודש שעבר.)

אתה זקוק לדפדפן המותאם ל- Java כדי להציג יישומון זה

איור 2: כיתות המוטמעות בתוך כיתות

איור 3: עץ אלמנטים של יישומון (היררכיה)

כאשר משתמש מקיים אינטראקציה עם היישומון באיור 2, מערכת זמן הריצה של Java יוצרת מופע של אירוע בכיתה וממלאת את חברי הנתונים שלו במידע המתאר את הפעולה. מערכת זמן הריצה של Java מאפשרת ליישומון לטפל באירוע. זה מתחיל ברכיב שקיבל בתחילה את האירוע (למשל הכפתור עליו לחצו) ועובר במעלה עץ הרכיב, רכיב אחר רכיב, עד שהוא מגיע למיכל שבראש העץ. בדרך, לכל רכיב יש אפשרות להתעלם מהאירוע או להגיב אליו באחת (או יותר) מהדרכים הבאות:

  • שנה את חברי הנתונים של מופע האירוע
  • בצע פעולה ובצע חישוב כלשהו על סמך המידע הכלול באירוע
  • ציין בפני מערכת זמן הריצה של Java שהאירוע לא יתפשט במעלה העץ

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

ידית בוליאנית ציבורית אירוע (אירוע ה) 

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

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

שקול את התיאור הבא של אינטראקציה של משתמש דמיוני עם היישומון באיור 2. המשתמש לוחץ על הכפתור שכותרתו "אחד". מערכת זמן הריצה של שפת Java אוספת מידע על האירוע (מספר הקליקים, מיקום הקליק, הזמן בו התרחש הקליק והרכיב שקיבל את הקליק) ואורזת מידע זה במופע של מחלקת האירועים. מערכת זמן הריצה של Java מתחילה ברכיב עליו לחצו (במקרה זה הכפתור שכותרתו "One") ובאמצעות שיחה אל הרכיבhandleEvent()שיטה, מציע לרכיב אפשרות להגיב לאירוע. אם הרכיב אינו מטפל באירוע או מטפל באירוע באופן מלא (מסומן על ידי ערך החזרה כ- false), מערכת זמן הריצה של Java מציעה את מופע האירוע לרכיב הבא הבא בעץ - במקרה זה מופע של כיתת פאנל. מערכת זמן הריצה של Java ממשיכה בצורה זו עד לטיפול באירוע או למערכת זמן הריצה שנגמרת הרכיבים לנסות. איור 4 ממחיש את דרכו של אירוע זה כאשר היישומון מנסה לטפל בו.

איור 4: דרכו של אירוע

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

handle בוליאני ציבורי Event (אירוע evt) {if (evt.id == Event.ACTION_EVENT) {ta.appendText ("פאנל" + str + "ראה פעולה ... \ n"); } אחר אם (evt.id == Event.MOUSE_DOWN) {ta.appendText ("פאנל" + str + "ראה את העכבר למטה ... \ n"); }

החזר super.handleEvent (evt); }

רישום 1: handleEvent()שיטה אופיינית

שיטות עוזרות לאירועים

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

הנה רשימה של שיטות העוזר העומדות לרשות המתכנתים. אין שיטות עוזרות לסוגים מסוימים של אירועים.

action(Event evt, Object what)

gotFocus(Event evt, Object what)

lostFocus(Event evt, Object what)

mouseEnter(Event evt, int x, int y)

mouseExit(Event evt, int x, int y)

mouseMove(Event evt, int x, int y)

mouseUp(Event evt, int x, int y)

mouseDown(Event evt, int x, int y)

mouseDrag(Event evt, int x, int y)

keyDown(Event evt, int key)

keyUp(Event evt, int key)

שקר כדי לציין ששיטת העוזר לא טיפלה באירוע.

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

return super.handleEvent(e);

הקוד ברשימה 2 ממחיש כלל זה.

public boolean handleEvent(Event e) { if (e.target instanceof MyButton) { // do something... return true; }

return super.handleEvent(e); }

Listing 2: Rule for ending statement in handleEvent() method

Failure to follow this simple rule will prevent the proper invocation of helper methods.

Figure 5 contains an applet that handles mouse events solely through code placed in helper methods. The source code is available here.

Event evt The next event in a linked list of events.
Window events
Window events are generated in response to changes in the state of a window, frame, or dialog.
Event ID
WINDOW_DESTROY 201
WINDOW_EXPOSE 202
WINDOW_ICONIFY 203
WINDOW_DEICONIFY 204
WINDOW_MOVED 205
Keyboard events
Keyboard events are generated in response to keys pressed and released while a component has input focus.
Event ID
KEY_PRESS 401
KEY_RELEASE 402
KEY_ACTION 403
KEY_ACTION_RELEASE 404
Mouse events
Mouse events are generated in response to mouse actions occurring within the boundary of a component.
Event ID
MOUSE_DOWN 501
MOUSE_UP 502
MOUSE_MOVE 503
MOUSE_ENTER 504
MOUSE_EXIT 505
MOUSE_DRAG 506
Scroll events
Scroll events are generated in response to manipulation of scrollbars.
Event ID
SCROLL_LINE_UP 601
SCROLL_LINE_DOWN 602
SCROLL_PAGE_UP 603
SCROLL_PAGE_DOWN 604
SCROLL_ABSOLUTE 605
List events
List events are generated in response to selections made to a list.
Event ID
LIST_SELECT 701
LIST_DESELECT 702
Miscellaneous events
Miscellaneous events are generated in response to a variety of actions.
Event ID
ACTION_EVENT 1001
LOAD_FILE 1002
SAVE_FILE 1003
GOT_FOCUS 1004
LOST_FOCUS 1005
טוד סונדסטד מתכנת מאז שהמחשבים הפכו לזמינים במודלים שולחניים. אף על פי שהיה במקור מעוניין לבנות יישומי אובייקטים מבוזרים ב- C ++, טוד עבר לשפת התכנות של ג'אווה כאשר ג'אווה הפכה לבחירה ברורה עבור סוג זה. בנוסף לכתיבה, טוד מספק שירותי ייעוץ באינטרנט וביישומי אינטרנט לחברות בדרום-מזרח ארצות הברית.

למידע נוסף על נושא זה

  • מדריך ג'אווה מאת מרי קמפיונה וקתי ואלאת '. גרסת הטיוטה המקוונת זמינה בכתובת //java.sun.com/tutorial/index.html.

סיפור זה, "ג'אווה וטיפול באירועים" פורסם במקור על ידי JavaWorld.