פנלPluggable Look and Feel
תוכנית הדגמה
מטרת המחלקה הזו היא לבנות אובייקט שניתן יהיה לשייך אותו בקלות ל-GUI על-מנת לבחון את ה- GUI הזה לגבי כל יישומי ה- L&F המותקנים ב- JDK הנוכחית. כדי לשייך אובייקט זה ל- GUI בבדיקה, פשוט העבר הפניה ל- JFrame המכיל את ה- GUI כפרמטר במהלך בניית האובייקט. כרגיל, תיצור מופע לאובייקט מהמחלקה הזו ותוסיף אותו לאובייקט JFrame המופרד מה-GUI הנבדק. הקשר היחיד בין השניים יהיה שלאובייקט של מחלקה זו יש הפניה ל- GUI הנבדק כך שהוא יכול לשנות את ה- L&F של ה- GUI הזה.
מחלקה זו יוצרת JPanel. ה- JPanel מכיל JButtonl אחד עבור כל אחד מיישומי ה- L&F ב- JDK המותקנת הנוכחית. לחיצה על אחד ה- JButtons תגרום ל- L&F של ה- GUI הנבדק להשתנות ל- L&F שה- JButton הזה מייצג. (ה- L&F של האובייקט מהמחלקה הזו משתנים גם הם). השם של ה- L&F מוצג על ה- JButton.
מחלקה זו משמשת במגוון תוכניות בספר ההדרכה הזה על-מנת לבדוק אותן מול יישומי התצוגה והתחושה המותקנים הנוכחיים. משפטי המפתח לבחירת ואחר כך החלת ה- L&F החדשים הם:
UIManager.setLookAndFeel(plafClassName); SwingUtilities.updateComponentTreeUI(thisPlafPanel); SwingUtilities.updateComponentTreeUI(testGui); |
נמשיך לדון במשפטים אלה כאשר נדון בתוכניות בשיעור זה. מחלקה זו נבדקה באמצעות JDK 1.1.3 ו- Swing 1.01 תחת Win95.
פנל Pluggable Look and Feel
– מקטעי קוד מעניינים
מקטע הקוד המעניין הראשון מציג את משפטי הייבוא עבור תוכנית זו. הוא מובא פשוט כדי להזכיר לך שיהיה עליך לפעול בחבילת ה- Swing תוך שימוש ב-
“Pluggable Look and Feel” (כמו גם היבטים אחרים של Swing).
import java.awt.event.*; import com.sun.java.swing.*; import java.util.*; |
המקטע הבא הוא הצהרה של טיפוס משתנה התייחסות לא רגיל המשמש להתייחסות למערך של מידע לגבי L&F. באשר ל- Swing 1.0.1, המסמך שאמור להסביר את הטיפוס הזה נעדר מקבצי התיעוד להורדה. נראה שהמידע הזמין הטוב ביותר הוא המשפט הבא שהוצא מתוך תיאור המתודה המכונה getInstalledLookAndFeels() המחזירה אובייקט מערך מטיפוס זה (בציטטה זו תוקנה טעות דפוס קטנה על-ידי המחבר):
"מחזירה מערך של אובייקטים המספקים מידע מסוים לגבי יישומי ה- LookAndFeel שהותקנו בערכת הפיתוח הזו של ג'אווה. אובייקטי ה- LookAndFeelInfo יכולים לשמש יישום לבניית תפריט של אפשרויות תצוגה ותחושה עבור המשתמש או לקביעת התצוגה והתחושה בזמן ההפעלה.
להלן הצהרת משתנה ההתייחסות:
public class PlafPanel01 extends JPanel { UIManager.LookAndFeelInfo[] plafInfoArray; |
כדי שלמטפלי האירועים באובייקט של המחלקה הזו תהיה היכולת לשלוט על ה- L&F של GUI נבדק, חייבת להיות לאובייקט הפניה ל- GUI הנבדק הזה. הפניה כזו מועברת פנימה כפרמטר לפונקציה הבונה. כמו כן, כדי שלמטפל באירועים תהיה אפשרות לשלוט ב- L&F של אובייקט מהמחלקה הזו, חייבת להיות לו הפניה לאובייקט. המקטע הבא מציג שני משתנים המשמשים לשמירת שתי ההפניות הדרושות האלה:
JFrame testGui;//save a reference to the test GUI here PlafPanel01 thisPlafPanel = this;//ref to this object |
המקטע הבא מציג את ההתחלה של הפונקציה הבונה לאובייקט מטיפוס זה. שני המשפטים הראשונים באובייקט
· שומרים את ההפניה הנכנסת לאובייקט ה- GUI הנבדק
· יוצרים Lable המכילה כינוי ללוח הבקרה של ה- PL&F.
public PlafPanel01(JFrame testGui) {//constructor this.testGui = testGui;//save ref to test GUI this.add(new JLabel(//label the PlafPanel "PL&F Selection Panel, Copyright 1998, RGBaldwin")); |
זה מביא אותנו מהשלב המקדים אל תוככי האובייקט. המקטע הבא מביא מערך המכיל רשימה של כל יישומי ה- L&F הכלולים בהתקנת ה- JDK הנוכחית. המתודה המשמשת במקטע זה נידונה כבר קודם.
plafInfoArray = UIManager.getInstalledLookAndFeels(); |
כאשר יש בידינו את הרשימה של יישומי ה- L&F, עלינו ליצור אובייקט JButton שישמש להפעלת כל אחד מיישומים אלה. מכיוון שאנו לא יודעים כמה יישומים כאלה יותקנו ב- JDK המותקנת הנוכחית, נשתמש באובייקט Vector כדי להכיל הפניות לאובייקטי ה- JButton האלה. יוצרים מופעים לאובייקטי ה- JButton בלולאת for שעושה איטראציה אחת לכל אחד מהאלמנטים במערך של יישומי L&F. ההצהרה של ה- Vector וההתחלה של לולאת ה- for עם משפט לאיתחול ה- Vector מוצגים במקטע הקוד הבא.
Vector theButtons = new Vector(plafInfoArray.length); for(int cnt = 0; cnt < plafInfoArray.length; cnt++){ theButtons.addElement(new JButton()); |
יהיה לנו צורך בשם של מחלקת ה- L&F המשויך לכל אחד מהאלמנטים במערך ה- L&F מכמה סיבות, לכן מקטע הקוד הבא מחלץ את השם ושומר אותו במשתנה התייחסות הנקרא theClassName.
//Still in the for loop String theClassName = plafInfoArray[cnt].getClassName(); |
אחד השימושים של השם של מחלקת ה- L&F הוא יצירת תוויות עבור כל אחד מאובייקטי ה- JButton המשמשים להפעלת ה- L&F החדש. המחרוזת השלמה של שם המחלקה היא ארוכה למדי. אנו נחלץ שם קצר עבור כל יישום L&F ספציפי ונשתמש בו כדי לתת תווית ל- JButton התואם ל- L&F הזה. השם הקצר בו נשתמש מופיע לאחר הנקודה האחרונה בפירוט המחרוזת של שם המחלקה עבור יישום ה- L&F, אז נשתמש במניפולציית מחרוזת פשוטה כדי לחלץ את השם. שים לב לדרישה לעשות downcast להפניה שתחולץ מה- Vector.
//Still in the for loop String label = theClassName.substring( theClassName.lastIndexOf(".")+1); ((JButton)theButtons.elementAt(cnt)).setText(label); |
לאחר מכן, אנו יוצרים מופע לאובייקט Action Listener ומשייכים אותו בכל אחד מאובייקטי ה- JButton. כאשר לוחצים על הלחצן, הקוד במתודה actionPerformed() של אובייקט המאזין גורם ל- L&F להשתנות ל- L&F המסוים שמייצג הלחצן. זכור כי מכיוון שההפניות ללחצנים מאוחסנות כטיפוס אובייקט ב- Vector, יש לעשות להן downcast לפני שניתן יהיה להשתמש בהן. גם שם מחלקת ה- L&F נחוץ למטפל באירועי פעולה
(Action Event handler), אז אנו מעבירים אותו כפרמטר לפונקציה הבונה עבור אובייקט המאזין.
((JButton)theButtons.elementAt(cnt)). addActionListener(new MyActionListener( theClassName)); |
לסיום, עדיין בלולאת ה- for, מוסיפים כל אחד מה- JButton ל- Jpanel. זה יהיה סוף לולאת ה- forוגם סוף הפונקציה הבונה.
//Still in the for loop //Add each JButton to the JPanel. add((JButton)theButtons.elementAt(cnt)); }//end for loop }//end constructor |
מקטע הקוד הבא מציג את ההתחלה של מחלקה פנימית המשמשת ליצירת מופעים לאובייקטי ה- Action Listener. שים לב, שלמרות שזוהי מחלקה פנימית, היא אינה מחלקה פנימית אנונימית. מקטע הקוד הבא מציג את הפונקציה הבונה עבור אובייקט המאזין השומר את השם של מחלקת ה- L&F המשויך ללחצן שבו רשום המאזין.
class MyActionListener implements ActionListener{ String plafClassName;//save name of plaf class here MyActionListener(String plafClassName){ this.plafClassName = plafClassName; }//end constructor |
המתודה actionPerformed() היא הלב של כל אובייקטי Action Listener. מקטע הקוד הבא מציג את ההתחלה של מתודה זו המפעילה את המתודה הסטטית setLookAndFeel() של המחלקה UIManager כדי להגדיר את ה- L&F הנוכחי המשמש כברירת מחדל. מתודה זו זורקת מספר טיפוסים שונים של חריגות בתחום של הבלוק try/catch.
public void actionPerformed(ActionEvent e){ //Set the current default L&F to that passed in as // a parameter try{ UIManager.setLookAndFeel(plafClassName); }catch(Exception ex){System.out.println(ex);} |
עצם הקביעה של ה- L&F הנוכחי המשמש כברירת מחדל לא גורמת לו להיות המשפיע. אלא, יש לבצע פעולה מסוימת כדי לגרום ל- L&F החדש להשפיע.
מקטע הקוד הבא השיג זאת על-ידי הפעלת המתודה הסטטית updateComponentTreeUI() על שתי הפניות שונות:
· ההפניה ל-GUI הנבדק
· ההפניה ללוח הבקרה של ה- L&F
התיאור של מתודה זו כפי שחולץ מתיעוד ה- Swing הוא כדלהלן:
"שינוי פשוט של התצוגה והתחושה: בקש מכל אחת מהצמתים בעץ ל- updateUI(), זאת אומרת, לאתחל את מרכיב ה- UI שלה בתצוגה והתחושה הנוכחיות. "
הקוד הבא יגרום הן ל- GUI הנבדק והן לפנל המכיל את לחצני ה- L&F לשקף את ה- L&F החדש שנבחר באמצעות לחיצה על אחד הלחצנים.
//Set the L&F for this PlafPanel01 object SwingUtilities.updateComponentTreeUI(thisPlafPanel); //Set the L&F for the test GUI object SwingUtilities.updateComponentTreeUI(testGui); }//end actionPerformed() }//end class MyActionListener }//end class PlafPanel01 |
זהו סוף ההגדרה של המתודה actionPerformed(), סוף המחלקה Action Listener, וסוף המחלקה PlafPanel101. פירוט מלא של התוכנית הזו כלול בסעיף הבא. התוכנית הנידונה בסעיפים המופיעים לאחר פירוט התוכנית גורמת למחלקה הזו לעבוד על-ידי כך שהיא משתמשת בה להפעלת יישומי L&F שונים על GUI פשוט המורכב מ- JButton ו- JTextField .