<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    當(dāng)柳上原的風(fēng)吹向天際的時候...

    真正的快樂來源于創(chuàng)造

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
    傳統(tǒng)的Swing工具欄的按鈕從生成到響應(yīng)總是需要一堆相似的代碼來完成的,如下:
    生成工具欄按鈕的代碼示例:
    .....
    reopenBtn=new JButton(ResourceUtil.ToolbarMain_Reopen_ImageIcon);
    reopenBtn.setToolTipText(
    "刷新數(shù)據(jù)庫內(nèi)容");
    toolbar.add(reopenBtn);
    // toolbar是工具欄,JToolBar的示例


    響應(yīng)上面這個按鈕的點擊事件的代碼如下:
    view.getToolbarPanel().getReopenBtn().addActionListener(new ActionListener() {
        
    public void actionPerformed(ActionEvent e) {
            .. 
    // 具體處理略
        }
    });


    如果只是這點代碼,程序整體確實沒有什么問題,但數(shù)量多了就不得了,試想想看,按照MVC的放置原則,生成的代碼和響應(yīng)點擊的代碼應(yīng)該放在兩個類中,如果需要修改就是兩個修改點;而工具欄按鈕一般是較多的,假設(shè)有十個按鈕那么就意味著十對修改點,如果數(shù)量再多呢?這對軟件的可維護性可謂一個災(zāi)難,也為系統(tǒng)的隱患埋下了伏筆。有人說這就要考驗維護者對系統(tǒng)的理解和對代碼的責(zé)任心了,對這種轉(zhuǎn)移問題和把維護人員等同于機器的觀點作者不敢茍同,框架的設(shè)計者不能把自己應(yīng)該盡到的責(zé)任推卸給維護者。

    如果有效利用XML和反射等手段,我們可以做到工具欄菜單項的可配置化。具體來說就是,將菜單項的文字,圖片和點擊后的響應(yīng)函數(shù)都在XML配置文件中配置好,程序啟動時去讀取文件生成菜單,點擊菜單項后會動態(tài)的通過反射找到具體需要處理的函數(shù)。這樣做以后,修改一個按鈕對應(yīng)的功能定位代碼,或是增刪一個按鈕及其功能就很容易了。下面來看具體的做法:

    1.工具欄菜單的配置文件
       <items>    
            
                
            
    <item>
                
    <icon>tollbar_sqlwindow/run.gif</icon>
                
    <function>run</function>
                
    <description>執(zhí)行所選擇的Sql語句</description>
            
    </item>
            
            
    <item>
                
    <icon>tollbar_sqlwindow/batchRun.gif</icon>
                
    <function>batchRun</function>
                
    <description>批量執(zhí)行所選擇的Sql語句,以分號為分割單位</description>
            
    </item>
            
            
    <item>
                
    <icon>tollbar_sqlwindow/format.gif</icon>
                
    <function>format</function>
                
    <description>格式化所選擇的Sql語句</description>
            
    </item>
            
            
        
    </items>
     
    以上子項里,icon是工具欄按鈕的對應(yīng)圖片,function是點擊按鈕后響應(yīng)的具體函數(shù)名,description是用于ToolTipText的文字,這些信息都會被程序讀取出來。

    2.讀取配置文件中的信息
        List<ToolbarItem> items=new ArrayList<ToolbarItem>();
        
        
    // 下面開始讀取sqlWndToolbar.xml得到菜單項
        try {
            SAXReader reader 
    = new SAXReader();
            InputStream is
    =TreeMenuPanel.class.getResourceAsStream(“sqlWndToolbar.xml”);// toolbar.xml是具體文件名
            
            Document document 
    = reader.read(is);
            Element rootElm 
    = document.getRootElement();
            
            List
    <Element> elms = rootElm.elements("item");
            
    for (Element elm : elms) {
                String icon
    =elm.elementText("icon");
                String function
    =elm.elementText("function");
                String description
    =elm.elementText("description");
                
                ToolbarItem btn
    =new ToolbarItem(icon,function,description);
                items.add(btn);
            }    
        } 
    catch (Exception ex) {
            DlgUtil.popupErrorDialog(
    "無法讀取文件"+ResourceUtil.SqlWndToolbar_XMLFile);
            ex.printStackTrace();
        }
        上述代碼中,ToolbarItem是包括icon,function,description 三個字符串子項的JavaBean。
        
    3.根據(jù)讀出的信息生成按鈕項并添加到工具欄。
       
        for (ToolbarItem item : ToolbarItemLoader.getItems()) {
            toolbar.add(
    new ToolbarButton(item.getIcon(), item.getFunction(),
                    item.getDescription()));
        }

    下面就是添加完成的工具欄:


        ToolbarItemLoader.getItems()會得到上面第二段代碼中的items的引用,然后遍歷得到子項后就可以生成按鈕了。但注意一下,生成的按鈕是自定義的ToolbarButton類實例而不是JButton的子類實例,ToolbarButton繼承自JButton但多了一個function屬性,這個屬性對于事件響應(yīng)是必不可少的,請看下面的代碼:
        
    4.添加工具欄菜單按鈕的事件響應(yīng):
    for (Component c : toolbar.getComponents()) {
        
    if (c instanceof ToolbarButton) {
            
    final ToolbarButton btn = (ToolbarButton) c;

            btn.addActionListener(
    new ActionListener() {
                
    public void actionPerformed(ActionEvent e) {
                    
    // 要執(zhí)行的函數(shù)
                    String function = btn.getFunction();

                    
    // 所選擇的文本
                    String selectedText = inputTxt.getSelectedText();

                    
    // 執(zhí)行函數(shù)
                    executeFunction(function, selectedText);
                }
            });
        }
    }

    上面代碼就顯示了ToolbarButton的function屬性,它作為一個函數(shù)的參數(shù)傳了出去,這個函數(shù)用反射來具體定位函數(shù),具體來說就是,function就是要真正調(diào)用的函數(shù)名。

    5.用反射調(diào)用具體的函數(shù)executeFunction.
    private void executeFunction(String fucntionName, String selectedText) {
        
    // 利用反射去找對應(yīng)函數(shù)
        try {
            
    // 得到實例對應(yīng)的類
            Class<?> cls = this.getClass();

            
    // 通過反射得到方法
            Method method = cls.getMethod(fucntionName,
                    
    new Class[] { String.class });

            
    // 通過反射調(diào)用對象的方法
            method.invoke(thisnew Object[] { selectedText });
        } 
    catch (NoSuchMethodException e) {
            
    // 找不到方法時

            DlgUtil.popupErrorDialog(
    "找不到方法" + fucntionName + ".");
        } 
    catch (IllegalAccessException e) {
            
    // 當(dāng)訪問權(quán)限不夠時

            DlgUtil.popupErrorDialog(
    "方法" + fucntionName + "的訪問權(quán)限不夠.");
        } 
    catch (InvocationTargetException e) {
            
    // 當(dāng)調(diào)用的函數(shù)拋出異常時
            Exception tragetException = (Exception) e.getTargetException();

            StringBuilder sb 
    = new StringBuilder();
            sb.append(
    "調(diào)用函數(shù)" + fucntionName + "出現(xiàn)異常,");
            sb.append(
    "具體的異常信息為" + tragetException.getMessage() + ".");

            SqlTextDialog dlg 
    = new SqlTextDialog("調(diào)用函數(shù)" + fucntionName
                    
    + "出現(xiàn)異常", sb.toString(), 400300);
            dlg.setVisible(
    true);
        }
    }

    通過以上的反射處理后,如果點擊的是
    <item>
        
    <icon>tollbar_sqlwindow/format.gif</icon>
        
    <function>format</function>
        
    <description>格式化所選擇的Sql語句</description>
    </item>

    這段信息對應(yīng)的按鈕,那么本類的format函數(shù)就會得到調(diào)用。
    public void format(String selectedText) throws Exception {

    }

    上面需要注意的有幾點:
    一是被反射調(diào)用的函數(shù)的訪問權(quán)限需要公有,否則會發(fā)生IllegalAccessException異常;二是函數(shù)名一定要和配置文件中的function節(jié)點對應(yīng)好,否則會拋出NoSuchMethodException異常,三是函數(shù)有自己的異常拋出后,需要用e.getTargetException()取得其真正異常。

    通過以上五步,按鈕的生成和響應(yīng)就可以被一個配置文件所控制,這種方式改善了程序的可維護性,反射是實現(xiàn)改進的五個步驟的核心環(huán)節(jié)。另外反射也是諸多框架和通用性組件的常用技術(shù)之一,值得每個程序員好好掌握。

    就是這些,再見吧!

    posted on 2010-05-18 22:04 何楊 閱讀(2380) 評論(7)  編輯  收藏

    Feedback

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-19 13:43 BeanSoft
    我個人認為如果采用 Netbeans RCP 或者新的 Swing Application Framework 會更好些. 只可惜了 JDK 1.4 下沒多少開發(fā)框架.  回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-19 14:20 何楊
    @BeanSoft

    建議很好啊,不過現(xiàn)在我還不熟悉它們,只能用熟的來開發(fā)了。  回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-19 17:25 kunrey
    可以看一下spring-richclient 采用的是這種思想,不過不會指定調(diào)用方法,這個稍微封裝一下應(yīng)該不難  回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-19 17:38 何楊
    @kunrey

    spring-richclient沒有接觸過。Spring什么時候弄出個桌面框架的?  回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-20 09:58 點對點
    @何楊
    spring-rich-client框架的思想非常不錯,看得使人賞心悅目的  回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-20 10:02 何楊
    @點對點

    謝謝,既然大家都說好,那看來要研究一番了。
      回復(fù)  更多評論
      

    # re: 使用反射簡化Swing工具欄菜單按鈕子項的設(shè)計 2010-05-21 11:04 何楊
    @點對點

    spring-rich-client才1.1.0版,再學(xué)一個桌面框架耗費挺大的,另外也不清楚它和Spring主體到底是什么關(guān)系,如果開發(fā)團隊力量小導(dǎo)致項目無疾而終就虧大了。我打算不預(yù)先抄底,等它成氣候再說。  回復(fù)  更多評論
      


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 青青免费在线视频| 亚洲日韩国产欧美一区二区三区 | 亚洲国产成人精品青青草原| 人人揉揉香蕉大免费不卡| 亚洲精品无码高潮喷水在线| 成在人线av无码免费高潮喷水 | 亚洲日本在线电影| 成人毛片免费观看视频| 国产人成亚洲第一网站在线播放| 国产精品视频永久免费播放| 中国亚洲呦女专区| 又粗又大又硬又爽的免费视频 | 亚洲国产美女视频| 久久不见久久见中文字幕免费 | 亚洲AV无码乱码在线观看裸奔| 国产永久免费高清在线| 亚洲av永久无码精品国产精品 | 国产福利免费在线观看| 最好2018中文免费视频| 久久久久亚洲精品无码网址 | 国产免费AV片在线播放唯爱网| 亚洲精品第一国产综合亚AV| 亚洲国模精品一区| 久久国产精品免费视频| 亚洲免费在线观看视频| 精品剧情v国产在免费线观看| 免费看一级高潮毛片| 亚洲av综合色区| 欧洲乱码伦视频免费| 精品亚洲福利一区二区| 亚洲国产精品无码专区影院| 国产在线观看片a免费观看 | 久久黄色免费网站| 亚洲狠狠成人综合网| 在线观看亚洲天天一三视| 99久9在线|免费| 黄页网站在线免费观看| 色婷婷六月亚洲婷婷丁香| 麻豆精品国产免费观看| 免费人成网站在线观看不卡| 亚洲乱人伦中文字幕无码|