המחלקה Event
בגלל השינויים שעומדים להתרחש בנושא זה של הAWT בכלל ושל ה 'טיפול באירועים' בפרט, אציין כי החומר של שיעור זה לקוח מ Java API Documentation 1.0.2. (תיעוד ה API של ג'אווה).
ה API מתאר את המחלקה Event כדלהלן:
"Event היא מחלקה שאינה תלויה בפלטפורמה המכמסת (encapsulates) אירועי משתמש מפלטפורמת ה GUI המקומית."
אני מעדיף להשתמש במינוח "פעילות משתמש" מאשר ב"אירועי משתמש" בכדי להימנע ממצב שבו יסתובבו בחלל יותר מדי פרשנויות למילה אירוע . במילים אחרות, מחלקה זו משמשת לריכוז ההודעות הרבות שמייצרת מערכת ההפעלה לתוך אובייקטים
שבהם יכולות האפליקציות ותוכניות הג'אווה שלנו לטפל ביתר קלות .
Event יורשת מ Object
המחלקה Event מתחילה עם השורה הבאה:
public class java.awt.Event extends java.lang.Object
לכן המחלקה Event יורשת מ Object באופן ישיר, שהיא כפי שידוע לך הרמה הגבוהה ביותר בהיררכית המחלקות של ג'אווה.
את המחלקה Event ניתן להפריד לחלקים הבאים:
- שדות, משתני מופע, יחידות נתונים(data members) (או איך שתבחר לקרוא להם),
- קבועים לשימוש השדה id .
- קבועים לשימוש השדה key
- קבועים לשימוש השדה modifiers
- פונקציות בונות
- מתודות
אנו נדון בכל אחד מחלקים האלה של Event באופן ניפרד.
שדות
השדות או משתני המופע הבאים במחלקה Event:
public Object arg;
public int clickCount;
public Event evt;
public int id;
public int key;
public int modifiers;
public Object target;
public long when;
public int x;
public int y;
יהיה חשוב מאוד להבין את השדות האלה מהסיבה הבאה:
בכל פעם שהמשתמש מעורב בפעולה מסוימת, מערכת ההפעלה תשלח הודעה למערכת run-time של ג'אווה שתכלא את המידע בנוגע לפעולה הזו בתוך אובייקט מסוג Event ותגרום לכך שהתוכנית שלנו תוכל להשתמש באובייקט הזה. (נדון בקצרה כיצד גורמים לכך שיהיה אפשר להשתמש בו). התוכנית שלנו היא זו שתהיה אחראית לפרש את המידע הזה ולהגיב בצורה מתאימה עם המשתמש. נזכיר שוב כי המידע הבא לגבי השדות נלקח מהתיעוד של Java API.
- arg: ארוגמנט רנדומלי של האירוע. הערך של שדה זה תלוי בסוג האירוע.
-clickCount : שדה זה מציין את מספרן של הלחיצות העוקבות עבור אירועי .MOUSE_DOWN עבור אירועים אחרים הוא אפס.
- evt: האירוע הבא. שדה זה מוגדר כשמכניסים אירועים לרשימה מקושרת.
- id : סוג האירוע.
- key : המקש עליו הקישו באירוע מקלדת.
- modifiers : מצב מקשי הmodifier-.
- target: מרכיב המטרה. הוא מזהה את המרכיב שעליו האירוע הופיע או שאליו קשור האירוע.
- when: חותמת הזמן של האירוע.
- x : קואורדינטת ה x של האירוע.
- y : קואורדינטת ה y של האירוע.
באופן כללי, רוב השדות האלה מסבירים את עצמם , ( אולי מלבד arg, evt , ו- target). חלק מהמידע בשדות, כמו לדוגמא id, key, ו- modifiers, מקודד כסדרה של ערכי integer.
אנו לא חייבים לדעת את הערך המספרי בכדי להשתמש במידע, אם כי ניתן לקבל את הערכים האלה בתיעוד של ה API.
לכל אחד מהערכים האפשריים עבור שדות אלה הוגדר קבוע תווי (a symbolic constant) בהגדרת המחלקה.
אם כך נעדיף, לכתוב קוד תוך שימוש בקבועים תוויים אלה במקום בערכים המספריים האמיתיים. שדות המידע של קואורדינטות הx- והy- מתארים את הקואורדינטות של העכבר, או של התקן הצבעה אחר, בזמן שהאירוע התרחש. השדה target מכיל reference לאובייקט שיצר את האירוע.
במילים אחרות, השם של אובייקט ההפנייה הוא זה שבאמצעותו מזהה התוכנית שלך את האובייקט הזה. נקודה זו תהיה ברורה יותר כשנראה את השדה targetבשימוש בפועל בתוכנית הדגמה. השדה arg הוא אובייקט מסוג Object ויכול להכיל מגוון סוגי מידע שונים, "תלוי בסוג האירוע".
בכדי ללמוד יותר על מבנה האובייקט הזה עבור אובייקט מסוים כלשהו, יהיה עליך לבדוק את המדריך עבור אותו מרכיב שלמעשה מעורב באירוע. מידע זה ניתן למצוא בתיעוד ה API שבמחלקה java.AWT.Component.
למשל, לפי תיעוד הAPI- אם האובייקט המעורב באירוע הוא אובייקט שייך למחלקה Button, "האובייקט שלה הוא תווית המחרוזת של הלחצן".
במילים אחרות, אם באירוע מסוים מעורב לחצן, התווית המופיעה על הלחצן תיכלא כמחרוזת
בשדה ה arg של אובייקט ה Event שנוצר על ידי מערכת run-time של ג'אווה.
מכיוון שמשתנה מופע זה הוא מסוג Object , התוכנית שלך תצטרך להמיר אותו לסוג המתאים לפני שתשתמש בו. אחר כך, יכולה התוכנית להשתמש בו לכל מטרה שתזדקק לה.
סקירה מקדימה על טיפול באירועים (Event Handling)
השיעור הבא ידון בטיפול באירועים באופן מעמיק. על כל פנים, בשלב זה, עלינו לתת סקירה כללית בכדי לקשור יחד את כל מה שנאמר. אנו נדון כעת בסקירה הכללית הזו, ואז נחדש את הדיון שלנו בחלקי ההצהרה של המחלקה Event.
כשאתה מתכנת במערכת GUI כל פעילות משתמש בעלת משמעות מזוהה עם אובייקט כל שהוא המופיע בסוג מסוים של תצוגה ויזואלית. (בשיעור זה מגמתנו תהיה להגביל את הדיון למערכות הדומות ל Windows, בלי Newtons בשלב זה בבקשה. ).
קיימות לפחות שתי דרכים לגרום לכך שפעילות משתמש תהפוך להיות מזוהה עם אובייקט במערכת טיפוסית:
-
להצביע על אובייקט ולעשות משהו
-
לעשות משהו במקלדת בזמן שיש לאובייקט את ה focus .
רובכם כבר מכירים את הסוגים האלה של פעולות המשתמש, אף על פי שאולי אף פעם לא הפסקתם לנתח את מה שאתם עושים.
הדרך הראשונה לזהות אובייקט עם פעולת משתמש היא פשוטה. באופן טבעי, היא כרוכה בהצבעה על האובייקט באמצעות כלי הצבעה (כמו העכבר למשל), ואחר כך ביצוע של פעולה כמו למשל לחיצה על העכבר, בחירת מחרוזת ברשימה, בחירת פריט מתוך תפריט, וכדו'…
הדרך השנייה לזהות אובייקט עם פעולת משתמש היא קצת יותר עקיפה ועשויה לדרוש הסבר נוסף. במערכת GUI , לאובייקט אחד (ורק לאובייקט אחד) שבכלי התצוגה יש את ה focus בכל זמן נתון. בדרך כלל, זה בולט מבחינה ויזואלית. האובייקט יהיה בצבע שונה, תהיה לו הילה (halo),
הוא יהבהב או שיהיה משהו שיפריד אותו משאר האובייקטים שבתצוגה. לדוגמא, במערכת Windows כאשר יש לאובייקטtext-entry את ה focus הוא מכיל סמן מצביע cursor) I-beam) מהבהב.
כשאין לו את ה focus הוא אינו מכיל סמן כזה. קיימות בדרך כלל מגוון דרכים שבאמצעותן ניתן לגרום לכך שיהיה לאובייקט את ה focus. הנפוצות מביניהן הן קרוב לוודאי לחיצה על האובייקט עם העכבר, או השימוש במקש tab בכדי להעביר את ה focus דרך סדרה של אובייקטים עד שהוא מגיע לאובייקט המבוקש.
כשיש לאובייקט מסוים את ה focus הוא יהיה האובייקט היחיד שיקבל קלט של המקלדת.
לכן, כשגורמים לכך שלאובייקט מסוים יהיה את ה focus, מכשירים את הקרקע לכך שפעולה של המקלדת תהיה מזוהה עם האובייקט הזה. לפעמים כל שנדרש הוא פשוט להצביע על האובייקט באמצעות העכבר ולחיצה עליו בכדי ליצור זיקה בין האובייקט ופעולה הנעשית עם העכבר. בחזרה אל ההנחה המקורית שלי, כשמתכנתים במערכת GUI כל פעולת משתמש משמעותית מזוהה עם אובייקט מסוים.
המחלקה Component
הבה נהיה עכשיו יותר ספציפיים. כשמתכנתים בג'אווה, כל האובייקטים מעין אלה הם מופעים של מחלקות היורשות באופן ישיר או עקיף מהמחלקה Component.
למחלקה Component מתודות רבות, שכולן זמינות עבור אובייקטים של מחלקות המופקות
מ Component .
המתודה המסוימת שמעניינת אותנו בשלב זה היא מתודה המכונה handleEvent().
זה השלב בו אנו סוף סוף לומדים כיצד הכל משתלב יחד.
- המשתמש עוסק בפעולה משמעותית כל שהיא.
- מערכת ההפעלה שולחת למערכת run-time של ג'אווה הודעה המכילה מידע על הפעולה הזו.
- מערכת run-time כולאת את המידע הזה באובייקט מסוג Event.
והצעד הבא, (וזה צעד מאוד מכריע לגבי היכולת שלך להבין כיצד הכל מסתדר יחד) הוא,
- מערכת run-time קוראת למתודה handle Event() של האובייקט המזוהה עם פעולת המשתמש,
תוך העברה של אובייקט ה Event כפרמטר.
בנקודה זו יכולה המתודה handleEvent() לעשות שלושה דברים:
- לטפל באירוע בשלמותו מבלי להשאיר עוד שום דבר לעשות.
- לטפל באירוע באופן חלקי כלשהו ולהשאיר חלק מהעבודה
- כלל לא לטפל באירוע.
במקרה הראשון, כשהצרכים של האירוע הנובעים מפעולת המשתמש טופלו באופן מלא,
מתודה handleEvent() אמורה להחזיר true כדי לסמן למערכת run-time שאין צורך בשום פעולה נוספת. במקרה השני והשלישי, HandleEvent() תחזיר false כדי לסמן למערכת run-time שיהיה צורך בעבודה נוספת.
במקרה האחרון הזה, מערכת run-time מזהה את האובייקט המכיל את האובייקט המקורי המזוהה עם האירוע. (יותר מאוחר, כשנלמד את מבנה ה GUI , תלמד כיצד אובייקט אחד יכול להיות מוכל בתוך אובייקט אחר).
אם ניתן לזהות אובייקט מכיל כזה, מערכת run-time קוראת למתודה handleEvent() של האובייקט המכיל כדי לבדוק האם היא רוצה לטפל באירוע.
המתודה handleEvent() של המכיל יכולה להגיב באחת מאותן שלוש דרכים.
התהליך הזה נמשך עד שהאירוע מטופל או עד שאין יותר מכילים בהיררכיה.
בשלב זה, מערכת run-time מפעילה טופס מסוים על התנהגות של ברירת מחדל ביחס לאירוע שפירושו כנראה התעלמות מוחלטת ממנו . כולכם מכירים את התופעה שלעיתים אתם יכולים ללחוץ על אובייקט ב GUI ויתעלמו לחלוטין מהלחיצה שלכם. (נסו פעם ללחוץ על אוביקט תווית ).
מתעלמים מהלחיצה שלך מכיוון שהמתכנת בחר שהתוכנה לא תגיב לפעולת המשתמש המסוימת הזו. נקווה שזה יעזור לך להבין כיצד הכל מתחבר יחד.
זו הייתה סקירה מאוד מהירה של 'טיפול באירועים' בג'אווה. באחד השיעורים הבאים, ניכנס לפרטים לגבי טיפול באירועים ונלמד על סוגים רבים של אירועים, ולמה באמת מתכוונים כשמדברים על כך. בינתיים, הבה נחזור אל מה שלמדנו על המחלקה Event , שממנה יוצרים מופעים לאובייקטים המאפשרים את כל הפעילות הזו.
Constructors (פונקציות בונות)
הצעד הבא שלנו בדרך להבנת אובייקטים של המחלקה Event הוא להתבונן בפונקציות הבונות (constructors) הזמינות. קיימות שלוש פונקציות בונות מועמסות למחלקה Event כפי שנראה להלן:
public Event(Object target, int id, Object arg);
public Event(Object target, long when, int id,
int x, int y, int key, int modifiers);
public Event(Object target, long when, int id,
int x, int y, int key,
int modifiers, Object arg);
הזמינות של הפונקציות הבונות האלה מציעה כמה אפשרויות מעניינות. זכור, כי בדיון הקודם אמרתי כי מערכת run-time של ג'אווה מגיבה למסר ממערכת ההפעלה ביצירת אובייקט מסוג Event והעברתו כפרמטר למתודה המכונה handleEvent() של האובייקט המזוהה עם האירוע.
עד עכשיו, לא אמרתי דבר על האפשרות לכתוב קוד היוצר מופעים לאובייקטים מסוג Event.
על כל פנים, מכיוון שהפונקציות הבונות קיימות ונגישות, אין דבר שיכול למנוע ממך לעשות זאת.
גישה אל הפונקציות הבונות פירושה שלקוד באפליקציה של ג'אווה יש את היכולת ליצור מופע לאובייקטים מסוג Event ולשגר אותם ממש כאילו מערכת run-time יצרה להם מופעים בתגובה לפעולת משתמש. אנחנו כבר יודעים די בכדי להיות מסוגלים ליצור מופע לאובייקט מסוג Event,
מכיוון שאנו מבינים (או יכולים להסיק) כיצד לספק את הארגומנטים הנחוצים עבור הפונקציות הבונות הנ"ל.
אנחנו עדיין לא יודעים כיצד לשגר את האובייקט, אבל אנחנו נלמד כיצד לעשות זאת יותר מאוחר. לאחר מכן, באפשרותנו ליצור כמה אפקטים ממש מתוחכמים.
כהערה צדדית נוספת, האם ניסית אי פעם להחליף בתוכנית את סמן שעון החול עם הסמן המצביע ואז לצפות כיצד אחרים משתמשים בתוכנית , אפילו כשהם יודעים שהסמנים הוחלפו?
ניסוי כזה יכול להדגים בבירור את כוחם של סמלים ויזואליים כאמצעי ליצירת תקשורת.