מימוש ממשק משתמש ע"י GUIDE שיעור מס' 12: שימוש ב- GUIDE - GUIDE ראשי תיבות של - GUI Design Environment הוא כלי ליצירה חצי-אינטראקטיבית של ממשקי-משתמש. תהליך העבודה עם GUIDE הפעלת GUIDE ליצירת ממשק חדש - להפעיל פקודת guide מחלון הפקודות. לעבודה על ממשק קיים: guide filename.fig עם שם הקובץ הגרפי: guide להפעיל פקודת.open in GUIDE כשהסמן על הקובץ הגרפי בחלון הקבצים, ולבחור context menu או לפתוח שלבי התהליך עיצוב ויזואלי/גרפי: קביעת ממדיו של חלון הממשק וכן ממדיהם ומיקומם של פריטי הממשק. התאמת תכונות העצמים הגרפיים בממשק, באמצעות עורך התכונות. העריכה יכולה לקבוע איך העצמים ייראו )למשל גודל גופן(, אבל בעיקר חשוב לערוך תכונות הקשורות לתגובת העצמים לפעולות המשתמש ולזיהוי העצמים בתוך התוכנית. שמירת הממשק בשם מסוים. אם הממשק הנשמר חדש, המשתמש מתבקש לבחור שם לקבצים. שמירה נעשית ע"י: בחירת תפריט file ואז save או,save as או הפעלת הממשק ע"י לחיצה על כפתור ההפעלה )משולש ירוק בסרגל הכלים(. נוצרים שני קבצים בשם שנבחר: 1. קובץ גרפי )בפורמט מטלב מסוג )fig הכולל הן את העיצוב החזותי וכן תכונות לא-חזותיות של העצמים. 2. קובץ-תוכנית mfile עם תבנית מוכנה לפונקציות ה- callback, שהן פונקציות משניות.subfunctions כתיבת תוכניות ה- callback לתוך התבניות שבקובץ. )זה החלק הלא-אינטראקטיבי, והוא עיקר העבודה(. הפעלת הממשק הגרפי: הרצת קובץ ה- mfile )עם או בלי ארגומנטים של קלט או פלט(. הקשה על כפתור הרצה כאשר הקובץ הגרפי פתוח ב- GUIDE. בניית הקובץ הגרפי הוספת עצמים להוספת עצם לממשק, יש לבחור מסרגל העצמים שבצד שמאל את העצם מהסוג המבוקש ואז: להקיש על העצם בסרגל, ואז לסמן באזור העריכה מלבן שמציין את מימדי העצם ומיקומו, או... עמ' 1 מתוך 8
לגרור את העצם אל אזור העריכה למיקום הרצוי. העצם נוצר בגודל ברירת-מחדל. )אפשר לשנות את גודל העצמים בכל עת(. העצם נוצר עם תכונות ברירת-מחדל. הטקסט המוצג על העצם הוא ברירת המחדל גם של התגית שהעצם יקבל, וגם של הטקסט שיוצג )במקרים שטקסט משויך לעצם(. תגיות הן הבסיס להגדרות ולתכנות בעבודה עם GUIDE ולכן מומלץ לשנות ערכי ברירת-מחדל אלה לשמות משמעותיים למתכנת מייד לאחר יצירת העצם. עורך תכונות עורך תפריטים עורך תוכנית רשימת עצמים שינוי תכונות עצמים שינוי תכונות נעשה ב- Inspector Property שניתן לפתוח באחת מן האפשרויות הבאות: לבחור Property Inspector מתוך Context Menu )הקשה על עכבר ימני( של העצם. לעריכת תכונות החלון הגרפי כולו, יש להקיש על עכבר ימני כאשר הסמן נמצא בשטח העריכה אך לא מעל עצם כלשהו. הקשה כפולה על העצם. כפתור Property Inspector בסרגל הכלים בקצה העליון של המסך. העצם שייפתח עבורו העורך הוא זה שמסומן כ"נבחר". אם אף עצם לא מסומן, העורך ייפתח על תכונות החלון הגרפי. שינוי התגית נעשה ע"י שינוי ערך שדה Tag בעורך התכונות. שימושי התגית בתכנות הממשק:.guihandles של העצם באמצעות handle גישה למזהה מתן שם לפונקציות callback המשויכות לעצם: אם התגית שנבחרה היא Tag אז הפונקציה שמופעלת כאשר המשתמש בוחר בעצם נקראת Tag_Callback הערה: תכונת ה- Callback נקבעת אוטומטית ע"י GUIDE ולכן אין לשנות אותה באמצעות עורך התכונות. עמ' 2 מתוך 8
שינוי ברירות-מחדל ממשק חדש נוצר עם ברירת-מחדל עבור התכונות הכלליות. תכונות אלה הן: האם החלון הגרפי ניתן לשינוי או שממדיו קבועים )ברירת מחדל(. מהם התנאים להעברת הפוקוס לחלון הגרפי של הממשק: כאשר מתבצע Callback )ברירת מחדל( או בתנאים אחרים. :mfile מחדל: שניהם(. אם נוצר )ברירת mfile האם ליצור רק את העיצוב הגרפי או ליצור גם o האם ליצור תבניות עבור פונקציות Callback )ברירת מחדל: "כן"(. o האם כל הפעלה של הממשק פותחת חלון גרפי נוסף, או הפעלה יחידה - singleton )ברירת מחדל הפעלה יחידה(: הפעלה נוספת כאשר הממשק כבר פתוח מעבירה אליו את הפוקוס )ולא פותחת חלון חדש(. o האם להשתמש בסכמת הצבעים של המערכת כרקע )"כן" ברירת מחדל(. אם רוצים לשנות מאפיינים אלה, יש לעשות זאת לפני שמתחילים לעצב את הממשק, ע"י בחירה מתפריט.tools->GUI Options הערה: גם כאשר עובדים במסגרת של יצירה אוטומטית של תבניות עבור,Callbacks ניתן לערוך את ברירת המחדל עבור תכונת Callback ולכתוב במקומה כל דבר שמתאים לתכונה זו, כפי שתואר בשיעור 11. עבודה בצורה זו איננה מומלצת בדרך כלל, אבל עדיפה כאשר תגובת הממשק פשוטה ביותר ואין צורך בהגדרה מיוחדת של פונקציה. עיצוב קובץ הפקודות עבודה עם פונקציות משניות בקובץ אחד קובץ התוכנית שנוצר באופן אוטומטי ע"י GUIDE כולל את החלקים הבאים:.filename פונקציה ראשית בשם הקובץ filename_openingfcn תבנית לפונקציה משנית filename_outputfcn תבנית לפונקציה משנית תבנית לפונקציות משניות, אחת לכל תגית Tag_Callback )אם לכמה עצמים יש אותה תגית, כולם ישתמש באותו.)Callback יש לזכור שהסביבה הקוראת ל- callbacks היא סביבת מטלב הכללית. מאחר שפונקציות משניות אינן מוכרות לסביבה שמחוץ לקובץ שבו הן מוגדרות, מה מאפשר לסביבת מטלב להשתמש בהן כ- Callbacks? המנגנון שתואר בשיעור 11 לשיוך ה- callbacks לעצמים הרלוונטיים לא מתאים לעבודה עם :GUIDE העצמים לא נוצרים ע"י פקודות Uicontrol כחלק מן הפונקציה הראשית בקובץ; הם נוצרים באופן אינטראקטיבי ונשמרים בקובץ הגרפי, כאשר שיוך ה- callbacks נעשה ע"י.GUIDE הפתרון ש- GUIDE מספק קשור לאופן ההפעלה של קובץ התוכנית. התוכנית מגיבה בהתאם למספר הארגומנטים של קלט המועברים לה: 1. אם אין ארגומנטים של קלט: לפתוח את הממשק. 2. אם הארגומנט הראשון הוא מחרוזת תווים והשני הוא מזהה לעצם גרפי :)handle( בהנחה שהמחרוזת היא שם של אחת מפונקציות ה- callbacks, להפעיל את הפונקציה. עמ' 3 מתוך 8
3. אם הארגומנט הראשון הוא מחוזת תווים ויש יותר מ- 3 ארגומנטים של קלט: להעביר את כל הארגומנטים לטיפול של פונקציית-האתחול )כאן לא נפרט על צורת קריאה זו, פירוט נמצא בתיעוד(. אפשרות מס' 1 מתאימה לנאמר קודם על אופן הפעלת הממשק. אפשרות מס' 2 פותרת את הבעיה של זיהוי פונקציות משניות באופן הבא: כאשר משתמשים בברירת-מחדל של יצירה אוטומטית של,callbacks מטלב יוצר תכונת- callback עבור העצם כמודגם בצילום-המסך הבא: ראשית רואים שה- callback היא פונקציה אנונימית שמקבלת שני ארגומנטים של קלט: מזהה לעצם hobject ומידע על האירוע.eventdata זו הצורה הסטנדרטית שבה מטלב מפעיל.callbacks שנית, גוף הפונקציה האנונימית הוא למעשה קריאה לקובץ התוכנית )כלומר לפונקציה הראשית בו(. הארגומנט הראשון הוא מחרוזת תווים שכוללת את התגית שהוצמדה לעצם + התוספת _Callback )שאר הארגומנטים יתוארו בהמשך(. בהתאמה, נוצרת בקובץ הפקודות תבנית לפונקציה בשם זה. התוצאה היא שכאשר הממשק מופעל והעצם הגרפי מייצר אירוע, נקראת הפונקציה הראשית והארגומנט הראשון שמועבר אליה הוא שם ה- callback המתאים. ארגומנט זה מתאים לאפשרות מס' 2 למעלה, ומתבצעת קריאה ל- callback המתאים. הפונקציה הראשית - אין לשנותה הפונקציה הראשית בקובץ, כולל ההסבר על אופן פעולתה )הערות בתחילת הקובץ(, נוצרת באופן אוטומטי ע"י,gui_State הפונקציה מיישמת את המנגנון שתואר למעלה. מלבד איסוף-נתונים ושמירתם במשתנה בשם.GUIDE עיקר התהליך מתבצע באמצעות פונקציה מובנית של מטלב בשם.gui_mainfcn פונקציה זו מבצעת בדיקות שונות ומפעילה את פונקציית ה- callback או מעלה את הממשק, בהתאם לקריטריונים שתוארו למעלה. אתחול הממשק כולל את השלבים הבאים: יצירת החלון הגרפי. ברירת-המחדל היא לעשות זאת ע"י פתיחת הקובץ הגרפי שנשמר. )יש אפשרות נוספת שלא נפרט כאן(. בשלב זה מתבצעת הפוקנציה CreateFcn עבור כל העצמים הגרפיים. הוספת מידע מ- guihandles למידע הנמצא ב- guidata המשויך לחלון הממשק. הפעלת filename_openingfcn )פונקציה זו מאפשרת למתכנת להוסיף פעולות לשלבי האתחול(. הפעלת filename_outputfcn )פונקציה זו מגדירה ארגומנטים של פלט עבור הקובץ הראשי. ברירת המחדל היא ה- handle לחלון הגרפי הכללי(. שינוי בקוד הפונקציה הראשית יפגע בפעולה התקינה של הממשק. מבנה פונקציות ה- callback % --- Executes on button press in Tag. function Tag_Callback(hObject, eventdata, handles) % hobject handle to Tag (see GCBO) % eventdata to be defined in future % handles structure with handles and user תבנית פונקציה callback נראית כך: כאשר Tag הוא ערך התגית המשויכת לעצם. עמ' 4 מתוך 8
בארגומנט handles נמצא כל המידע שניתן לקבל באמצעות פקודת,guihandles בתוספת שדות שהוגדרו ע"י וע"י המשתמש. )עוד על העברת מידע, בהמשך(. בעזרת ארגומנט זה, כל אחת מפונקציות ה- callback GUIDE יכולה לזהות ולגשת לכל אחד מן העצמים בממשק. שני הארגומנטים הראשונים זהים לארגומנטים של callbacks כפי שהוסבר בשיעור 11. דוגמא 1: ממשק פשוט הכולל כפתור-לחיצה אחד ושלושה.radio buttons הממשק ממומש ע"י שני קבצים, d12simplegui h = d12simplegui ו- d12simplegui.m. d12simplegui.fig פתיחת הממשק: פתיחת הממשק וקבלת המזהה לחלון הגרפי h: כל כפתור-רדיו יכול להיות במצב on או.off במצב off ערכו )תכונת )Value שווה לערך תכונת Min ובמצב on ערכו )תכונת )Value שווה לערך תכונת.Max במטלב אין תלות בין שלושת הכפתורים, אולם מקובל להשתמש בכפתורי רדיו כאשר רוצים להראות שרק אחד מהם יכול להיות.on יצירת מצב זה נעשית ע"י תכנות פונקציות ה- callback כך שכל פונקציה ש"מפעילה" את הכפתור עליו המשתמש לחץ, גם "משביתה" את הכפתורים האחרים. לחיצה על כפתור Go רק מציגה בחלון הפקודות הודעה + ערך הארגומנט.handles כלים להעברת מידע בין הפונקציות GUIDE משתמש במנגנון של guidata כדי לשמור מידע, בין השאר על guihandles אבל לא רק. נזכיר את האפשרויות לשמירת מידע שצוינו בשיעור 11: הגדרת כל הפונקציות המשתפות מידע כפונקציות פנימיות של התוכנית הראשית: אפשרות זו לא ישימה כשעובדים עם,GUIDE מאחר שאין לגעת בקוד התוכנית הראשית, ואילו כל ה- callbacks מוגדרות כפונקציות משניות. שמירת המידע המשותף בתכונת UserData שניתן לשייכה לכל עצם גרפי. ישים גם ב- GUIDE. שימוש בעצם מסוג Application Data שניתן לשייכו לכל עצם גרפי. ישים גם ב- GUIDE. שימוש בתכונת guidata אשר משויכת לחלון הגרפי. ניתן להשתמש בתכונה זו גם ב- GUIDE, אבל בזהירות: GUIDE עצמו משתמש בתכונה זו לשמירת handles וכן עוד שדה אחד לפחות.)output( אפשר להוסיף שדות נוספים לצורך שמירת מידע, אבל לא "לדרוך" על המשתנה ולא למחוק שדות קיימים. יש לזכור שלמרות השם handles המשתנה מכיל גם מידע שאיננו מזהים של עצמים גרפיים. כמו-כן יש לעדכן את guidata לאחר כל שינוי שמבוצע ב- handles )בדומה לעדכון UserData או.)Application Data דוגמא 2: ממשק d12ecologygui חוזר על דוגמא 5 בשיעור 11, בהבדלים הבאים: מימוש ע"י.GUIDE מערכת-צירים נוספת לניתוח המידע..1.2 בכל פעם שמתעדכן הגרף במערכת הצירים העליונה, במערכת הצירים התחתונה מוצגת עקומה פרמטרית )תלוי במספר האוכלסיות שנבחרו(. לחיצה על כפתור Height vs. Time מציגה באותה מערכת צירים, במקום זה, גרף של גובה שיא כפונקציה של זמן השיא וכן קו מרוסק שמאפשר למשתמש לציין ערך-סף שמתחתיו שיא לא נלקח בחשבון באנליזה נוספת. לחיצה על כפתור Estimate T גורמת לביצוע והצגה של התאמה ליניארית בין מספר השיא לזמן עמ' 5 מתוך 8
השיא, כאשר נלקחים בחשבון רק השיאים שגובהם מעל ערך-הסף שצוין בשלב הקודם. מכאן מחושב ומוצג )בכותרת( זמן-המחזור של השיאים. נקודות לציון על המימוש בתוכנה: GUIDE מספק תבניות לפונקציות callback של עצמים הנראים בממשק הגרפי הסטטי. עצמים נוספים, למשל קווים שיש לעדכן בהמשך ו/או שמייצרים אירועים, יש להגדיר בגוף הקובץ וכן לכתוב עבורם callbacks ולשייכם לעצמים אלה. כל העקומות מאותחלות בשלב אתחול הממשק, ובהמשך רק מעדכנים אותן. כל האתחולים מתבצעים ב- Function.Opening העברת מידע בין הפונקציות בעזרת Application Data המשויך לחלון הראשי. בכל מצב מוצגים רק העצמים הרלוונטיים. למשל אם בוחרים,Grass+Deer מושבתים העצמים הקולטים מידע על אוכלוסיית האריות בזמן 0=t. בכל פעם שמתעדכן הגרף העליון, כפתור Estimate T מושבת )והוא מופעל רק לאחר לחיצה על.)Height vs. Time עבודה עם תפריטים סוגי תפריטים UImenu תפריט המוצג בסרגל התפריטים שלאורך השפה העליונה של החלון הגרפי. הקשה )עכבר שמאלי( על כותרת התפריט גורמת להצגת הפריטים הכלולים בו. תפריט זה משויך לחלון הגרפי. Uicontextmenu תפריט המשויך לעצם גרפי כלשהו, ואיננו מוצג. הקשה של עכבר ימני על העצם שאליו משויך התפריט, גורמת להצגת הפריטים. כל אחד מפריטי התפריט הוא עצם גרפי המשויך לתפריט. ניתן לבנות תפריט ולשייך את ה"שורש" שלו לתפריט אחר, וכך ליצור תפריטים בעלי כמה רמות. הממשק מגיב לבחירת פריט מסוים בהפעלת פונקציית callback המשויכת לפריט זה. עמ' 6 מתוך 8
העלה או הורד רמה הוסף פריט שנה סדר פריטים פקודות לבניית תפריטים hm = uimenu('pname','pval',...) הגדרת "שורש" ל- UImenu : hm = uimenu('label','file') ציון כותרת לתפריט: hm = uimenu('parent',hfig) ציון החלון אליו ישויך התפריט: hs = uimenu(hm,'label','save mat format') הוספת פריט לתפריט קיים: set(hs,'callback',@savematcallback) שיוך callback לפריט: hc = uicontextmenu הגדרת "שורש" ל- Uicontextmenu : set(hline,'uicontextmenu',hc) שיוך Uicontextmenu לעצם גרפי: הוספת פריטים ל- Uicontextmenu נעשית בצורה זהה ל- Uimenu, כלומר ע"י פקודת uimenu כמתואר למעלה. ניתן לציין תכונות נוספות לתפריטים, למשל מיקום )על החלון הגרפי או על סרגל התפריטים(. למידע נוסף יש לחפש בתיעוד uimenu properties או.uicontextmenu properties בניית תפריט באמצעות GUIDE יש לפתוח את עורך התפריטים ע"י הקשה על הכפתור המתאים בסרגל הכלים. לבחור בלשונית הרצויה: Menu Bar או.Context Menus לבחירת התפריט יש ללחוץ על הכפתור בסרגל הכלים המסומן בכוכבית * )בכל לשונית פעיל רק הכפתור הרלוונטי ללשונית זו(. מומלץ לבחור תגית בעלת משמעות מייד עם יצירת הפריט או התפריט. תפריט Uimenu יופיע בסרגל התפריטים כאשר הממשק יופעל. הוא אינו מופיע במסך העריכה של GUIDE מאחר שסרגל התפריטים איננו חלק מ"תוכן החלון" אלא נחשב לחלק מן ה"מסגרת/כותרת". עמ' 7 מתוך 8
את תפריט Uicontextmenu יש לשייך לעצם הרלוונטי ע"י פקודה, כמתואר בסעיף הקודם. בכל מקרה יש לעשות זאת בשלב האתחול של הממשק )בדרך כלל בפונקציה )Opening function ע"י מציאת המזהה )handle( הן של התפריט והן של העצם, והוספת המזהה של העצם כתכונת Uicontextmenu של העצם. קווים מנחים לעיצוב ממשק משתמש פשטות יש להציג רק מידע נחוץ. עיקרון זה נכון גם למידע המוצג וגם לעצמים לממשק. אם בשלב מסוים חלק מן המידע איננו נחוץ או רלוונטי, יש להעלים אותו. )במקרה של עצמים גרפיים לממשק, יש להשבית את העצמים שאינם רלוונטיים(. מיידיות אם ניתן להציג את התוצאות מייד, יש לעשות זאת. למשל לאחר תזוזה של סליידר יש להציג מייד את התוצאה )אם החישוב לא ארוך מדי( ולא להתנות את ההצגה בלחיצה על כפתור "הצג". גמישות במגבלות המקום בחלון הגרפי וכמות המידע שהמשתמש אמור לספק, יש לאפשר חלופות לקליטת מידע )למשל ע"י תיבת טקסט וגם סליידר(. עקביות יש לעצב ממשק לפעולות דומות באופן חזותי דומה. כמו-כן יש להשתמש בהליכים מוכרים, למשל בקליטת שם-קובץ מן המשתמש יש להפעיל uigetfile מאחר שהעיצוב של ממשק זה מתאים למוסכמות של המערכת. זה עדיף על עיצוב ייחודי של ממשק להצגת רשימת קבצים לבחירה. טיפול בשגיאות יש לחזות עד כמה שניתן מצבים שונים ולהיערך אליהם. במיוחד הממשק אמור לפעול גם אם המשתמש מגיב בדרכים "שגויות". משוב יש לספק למשתמש משוב על מצב המערכת בכל רגע נתון. בדרך כלל המשוב הוא הצגת התוצאות הרצויות. במקרים בהם קליטת הנתונים מורכבת מכמה שלבים, יש לספק רמזים מהו הצעד הבא. כמו-כן יש לתת משוב על מידע שגוי, לא מתאים או לא מספיק. סוף מעשה במחשבה תחילה... לתכנן מראש את הממשק, לפני שמתחילים בעיצוב בפועל: מהן המטלות. איזה מידע רלוונטי בכל שלב של התהליך, מה חשוב להציג בו-זמנית. איזה מידע המשתמש מספק, ובאילו דרכים )אינטראקטיבי, קריאה מקובץ(. אילו עצמים יקלטו מידע מן המשתמש ובאיזו דרך )סליידר, טקסט, כפתור וכו'(. איזה מידע יישמר בסופו של דבר, ובאיזו דרך. איך המערכת תגיב לפעולה של המשתמש בכל מצב שבו היא נמצאת. עמ' 8 מתוך 8