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

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

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

    京山游俠

    專注技術(shù),拒絕扯淡
    posts - 50, comments - 868, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
    上一篇:
    Eclipse RCP詳解(01):Hello World以及Eclipse RCP和OSGi的簡(jiǎn)單展示

      先來談?wù)勎覍?duì)GUI編程的體會(huì):
    GUI編程的本質(zhì)和難題:
      
    GUI編程一直都不簡(jiǎn)單,不管在什么平臺(tái)、用什么語言。而且項(xiàng)目越大就越難駕馭。如果追本溯源,會(huì)發(fā)現(xiàn)GUI編程的本質(zhì)就是窗口和消息循環(huán)。(本人比較了解Windows平臺(tái)和MFC框架,卻從未在X Window中使用任何庫編寫GUI程序,故以下探討皆來源于Windows系統(tǒng)的理論,如有不當(dāng),歡迎指正。)GUI不同于CLI,程序運(yùn)行時(shí)沒有固定的流程,程序界面必須能隨時(shí)響應(yīng)用戶的任何操作,當(dāng)然,也要響應(yīng)操作系統(tǒng)或其它程序?qū)Ρ境绦虻牟僮鳎虼顺绦蚪Y(jié)構(gòu)中必然存在一個(gè)循環(huán),在該循環(huán)中不停地獲取消息和響應(yīng)消息。在Windows系統(tǒng)中,一切界面元素,不管是對(duì)話框、文本框,還是菜單欄、工具欄按鈕,其本質(zhì)都是窗口。如果使用EnumWindow這個(gè)API枚舉一下操作系統(tǒng)中的窗口,會(huì)發(fā)現(xiàn)系統(tǒng)中的窗口數(shù)量遠(yuǎn)遠(yuǎn)多于我們見到的窗口數(shù)量。每一個(gè)窗口都能接受發(fā)送給它的消息,每一個(gè)類型的窗口都有一個(gè)消息處理函數(shù)用來處理發(fā)送給它的消息。窗口之間通過互相發(fā)送消息而通訊。
      以上所描述的GUI系統(tǒng)機(jī)制看似脈絡(luò)清晰、簡(jiǎn)單自然,但是卻沒有多少人愿意用這些反撲歸真的底層API去編寫自己的GUI程序。因?yàn)槠渲刑N(yùn)含著兩個(gè)難題:1、直接使用底層API非常麻煩,必須經(jīng)過適當(dāng)?shù)姆庋b;2、程序越大,則窗口對(duì)象越多,它們之間的通訊越復(fù)雜,如果不經(jīng)過精心組織,則非常難以管理。
      為了解決以上難題,不同平臺(tái)、不同編程語言及不同的程序庫都會(huì)對(duì)底層API進(jìn)行封裝。這些封裝基本上都會(huì)從兩個(gè)方面著手:1、將不同的窗口封裝為不同的控件,大的如Frame、Dialog,小的如Button、Label,并且都提供方便的方法來設(shè)置這些控件的外觀;2、提供某種事件機(jī)制響應(yīng)用戶對(duì)GUI的操作。
      有人可能會(huì)說Java中的Swing沒有使用底層API,它所有的控件都是自己畫出來的。但是Java對(duì)GUI的封裝依然離不開我上面說的兩點(diǎn)。
    不同編程語言特性帶來的難度:
      由于編程語言自身的特性,在使用封裝好的GUI組件時(shí)仍然有不同的難易性。最簡(jiǎn)單的應(yīng)該算是VB之類,拖拖拉拉就可以創(chuàng)建一個(gè)GUI界面,要處理哪個(gè)控件的事件就設(shè)置哪個(gè)控件的事件處理函數(shù),其次是JavaScript,先使用HTML定義好界面,然后定義各個(gè)控件的事件處理函數(shù)即可。不過上面所說的簡(jiǎn)單也只能算是入門簡(jiǎn)單,如果要寫大規(guī)模的程序,它們?nèi)匀槐苊獠涣舜罅康目丶o法合理組織管理這樣的難題。
      最難的應(yīng)該算是C++,因?yàn)樗畹讓印FC對(duì)各種控件都做了不錯(cuò)的封裝,也提供了SDI、MDI和基于對(duì)話框的程序這樣的框架,大大簡(jiǎn)化了使用C++開發(fā)GUI程序的難度,但它依然還是最難的。在MFC中是通過消息映射來處理事件的,如果要處理某個(gè)窗口的事件,必須得創(chuàng)建自己的窗口類,并定義大量的事件處理函數(shù)。對(duì)于大規(guī)模的程序,仍然有大量對(duì)象不好合理組織的難題。
      用Java語言編寫GUI程序介于以上兩種之間。Java語言的面向?qū)ο蠓庋b做得非常好,GUI編程理解起來不難。其流程也是先使用諸如JFrame、JButton、JText之類的控件構(gòu)建一個(gè)GUI界面,然后再處理各個(gè)控件的事件。但是也正是因?yàn)镴ava語言在面向?qū)ο筇匦苑矫娴倪^分完美,給GUI編程帶來的額外的復(fù)雜性。其表現(xiàn)體現(xiàn)在兩個(gè)方面:1、在Java中一切皆是對(duì)象,所以在設(shè)置一個(gè)控件的事件處理器時(shí),傳遞給它的必須也是一個(gè)對(duì)象,而前面提到的幾種編程語言都可以直接設(shè)置事件處理器為一個(gè)函數(shù),可以把函數(shù)或函數(shù)指針當(dāng)參數(shù)傳遞。所以在使用Java編寫GUI程序時(shí)往往需要編寫大量的EventHandler類,哪怕編寫這些類只是為了定義一個(gè)函數(shù),然后實(shí)例化出一個(gè)對(duì)象。當(dāng)然,隨著Java語言的不斷改進(jìn),我們可以通過內(nèi)部類、匿名類、Lambda表達(dá)式來減少編寫EventHandler類的工作,在Java8中,甚至可以直接傳遞方法引用。個(gè)人認(rèn)為,以上語言特性在提供了方便的同時(shí),有點(diǎn)破壞Java面向?qū)ο缶幊痰耐昝佬浴?、對(duì)象可見性的問題,不像VB、JavaScript,定義一個(gè)全局變量后則全世界都可以訪問到,在Java中則不行,一個(gè)對(duì)象要訪問另一個(gè)對(duì)象學(xué)問可就深了,特別是為了解決上一個(gè)問題而出現(xiàn)的內(nèi)部類、匿名類,它們想要訪問外部類外面的對(duì)象容易嗎?Java中的閉包就是為了解決這樣的問題,但我認(rèn)為這不是完美的解決方案。
    設(shè)計(jì)模式在GUI編程中的應(yīng)用:
      在前面的探討中,我反復(fù)提到一旦程序規(guī)模過大,則大量的對(duì)象難以管理,這些對(duì)象之間的相互通訊更是錯(cuò)綜復(fù)雜。這個(gè)時(shí)候就必須靠設(shè)計(jì)模式來解決問題了。首先,幾乎所有的GUI程序都是按照樹形結(jié)構(gòu)組織起來的,父控件包含子控件,子控件再包含更多的子控件,這樣一級(jí)一級(jí)的包含下去。最后只需要把頂層的控件暴露出來,就可以順著路徑找到其它的控件。其次,MVC模式在GUI編程中廣泛使用。比如MFC中的SDI和MDI,都有一個(gè)Document對(duì)象,修改Document對(duì)象的狀態(tài)后,再刷新視圖的顯示。最后,還有眾多的諸如工廠模式、單例模式、監(jiān)聽器模式、過濾器模式等等在GUI編程中廣泛使用。
    編寫GUI程序不能從零開始,要適當(dāng)使用框架:
      這一點(diǎn)應(yīng)該不需要仔細(xì)論證。這也是我們使用Eclipse RCP編程的初衷。
    Eclipse的Runtime和UI:
      我們可以認(rèn)為Eclipse RCP是一個(gè)很適合我們使用的編寫GUI程序的起點(diǎn)。在本篇博文中,我正是要對(duì)Eclipse的Runtime和UI進(jìn)行探討。因?yàn)椴豢赡芤幌伦訉懙煤苌钊耄栽跇?biāo)題中稱為“初探”。Eclipse的Runtime提供了很多功能,比如對(duì)配置首選項(xiàng)的支持、對(duì)ContentType的支持、對(duì)安全存儲(chǔ)的支持、對(duì)結(jié)構(gòu)化文本的支持、對(duì)網(wǎng)絡(luò)和代理的支持、甚至還有一個(gè)多線程框架(貌似已經(jīng)deprecated),這些功能我統(tǒng)統(tǒng)不感冒。(當(dāng)然,如果程序的功能正好需要這些底層支持,用一下也無妨。)Eclipse的Runtime最引人注目的當(dāng)然是它的插件機(jī)制了。插件機(jī)制可以帶來這樣的優(yōu)點(diǎn):開發(fā)項(xiàng)目時(shí),我們可以先編寫一個(gè)核心的程序?qū)崿F(xiàn)最基本的功能,然后把程序需要實(shí)現(xiàn)的其它功能進(jìn)行劃分,每一個(gè)功能單獨(dú)做成一個(gè)Plugin插入到核心中即可。不難看出,使用這樣的結(jié)構(gòu)的程序添加和刪除功能都非常方便,可以大大降低項(xiàng)目失敗的風(fēng)險(xiǎn)。Eclipse的UI更是提供了獨(dú)具一格的界面風(fēng)格和程序框架,使用Eclipse RCP,我們當(dāng)然不需要從頭開始實(shí)現(xiàn)一個(gè)窗口,只需要添添補(bǔ)補(bǔ),就可以讓程序擁有完美的菜單、工具欄、視圖、編輯器等一系列的界面元素。
      要使用Eclipse的Runtime和UI提供的功能,我們需要熟悉兩個(gè)工具類,它們是:
        org.eclipse.core.runtime.Platform
        org.eclipse.ui.PlatformUI

      我們先來熟悉一下Eclipse的UI是怎么組織的,以及其中的一些基本概念。在上一篇中,我展示了一個(gè)HelloWorld程序,通過該程序,應(yīng)該不難了解什么是視圖。除了視圖之外,在HelloWorld程序中還有一個(gè)編輯器區(qū)域,但是我們沒有實(shí)現(xiàn)任何編輯器。視圖和編輯器放在一個(gè)稱為Workbench Page的容器中,一個(gè)Workbench Page可以容納多個(gè)編輯器和視圖。Workbench Page又是放在一個(gè)稱為Workbench Window的容器中。Workbench Window則是我們程序的主窗口,Workbench Window中還可以包含菜單欄、工具欄及狀態(tài)欄。不同于其它框架開發(fā)出的程序,Eclipse還有一個(gè)比較有特色的UI特性,那就是每一個(gè)視圖都可以有自己的菜單欄和工具欄。經(jīng)常使用Eclipse的開發(fā)者對(duì)以上概念應(yīng)該不陌生。Eclipse各個(gè)組件的層次關(guān)系如下圖:

      Workbench Window其實(shí)還有上一級(jí),那就是Workbench。理論上講,一個(gè)Workbench可以有多個(gè)Workbench Window,但是同一時(shí)刻只能有一個(gè)Workbench window是Active的,也只有一個(gè)是可見的。事實(shí)上,我們見到的程序一般都只有一個(gè)Workbench Window。同樣,一個(gè)Workbench Window可以有多個(gè)Workbench Page,但同一時(shí)刻,也只有一個(gè)是Active的和可見的。以上情況不同于視圖,因?yàn)槎鄠€(gè)視圖可以同時(shí)顯示。我們把一組視圖和編輯器的初始布局稱為透視圖(Perspective)。Workbench Window可以切換Page,每一個(gè)Page初始顯示時(shí)都是以透視圖為模板來組織視圖和編輯器。
      當(dāng)我們需要使用Workbench、Workbench Window、Workbench Page的功能時(shí),可以使用如下接口:
        org.eclipse.ui.IWorkbench
        org.eclipse.ui.IWorkbenchWindow
        org.eclipse.ui.IWorkbenchPage
      以上接口不需要我們自己去實(shí)現(xiàn),這些接口指向的對(duì)象也不需要我們?nèi)?shí)例化,只需要調(diào)用PlatformUI.getWorkbench()、PlatfromUI.getWorkbench().getActiveWorkbenchWindow()以及PlatfromUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()即可分別得到以上對(duì)象。(當(dāng)然,也可以通過Id獲得不是Active的Window和Page。)

      除了窗口、視圖和編輯器,Eclipse UI中的另外一部分就是菜單和工具欄了。在SWT中,菜單欄、菜單項(xiàng)、工具欄、工具欄按鈕屬于最基本的控件。直接使用這些控件是可行的,但是肯定很麻煩,所以JFace對(duì)它們做了一次封裝。封裝后就成了Action。在我五年前寫的文章中,菜單和工具欄就是使用Action實(shí)現(xiàn)的。但是Action還是沒有把菜單、工具欄的外觀和行為徹底分開,所以Eclipse中又出現(xiàn)了command和handler機(jī)制。
      在Helloworld程序中,大家已經(jīng)看到了HelloWorldView是怎么通過定義org.eclipse.ui.views擴(kuò)展添加到程序界面中的。菜單和工具欄也可以通過定義相應(yīng)的擴(kuò)展而增加到Workbench Window中。在我五年前寫的文章中我們使用了org.eclipse.ui.actionSets擴(kuò)展。今天,我們不使用Action,而是使用全新的Command機(jī)制。
      不同于Action,Commands通過三步有效的達(dá)到界面表現(xiàn)和內(nèi)部實(shí)現(xiàn)的分離:首先,通過 org.eclipse.ui.commands 擴(kuò)展點(diǎn)創(chuàng)建命令和類別(Category),并且可以把某些命令放在一個(gè)類別(Category)中;然后,通過 org.eclipse.ui.menus 指定命令出現(xiàn)在界面的哪個(gè)區(qū)域(視圖菜單/主菜單/上下文菜單);最后通過 org.eclipse.ui.handlers 指定命令的實(shí)現(xiàn)。因此,Eclipse 推薦使用Commands 來創(chuàng)建菜單。在定義org.eclipse.ui.menus擴(kuò)展時(shí),需要使用到locationURI來指定菜單出現(xiàn)的位置,locationURI的格式不難,大家可以看Eclipse的參考文檔。

      下面開始看實(shí)例。為了展示Eclipse的底層功能,我設(shè)計(jì)了這樣一個(gè)例子:在程序中有兩個(gè)視圖和兩個(gè)菜單項(xiàng),其中一個(gè)視圖中是一個(gè)SWT的List控件,當(dāng)點(diǎn)擊菜單項(xiàng)“Show Bundles”時(shí),在這個(gè)List中顯示所有的Bundle,另一個(gè)視圖中是一個(gè)SWT的Tree控件,當(dāng)點(diǎn)擊菜單項(xiàng)“Show Extensions”時(shí),在這個(gè)Tree中顯示所有的擴(kuò)展點(diǎn)和擴(kuò)展。
      第一步,先實(shí)現(xiàn)兩個(gè)視圖的界面,如下圖:


      這兩個(gè)視圖中一個(gè)是List控件,一個(gè)是Tree控件,使用AbsoluteLayout。界面很簡(jiǎn)單,根本不需要?jiǎng)佑肳indowBuilder這樣的神器,直接寫代碼即可,如下:




      這個(gè)程序的界面和HelloWorld相比有兩處不同,一是窗口變大了,二是沒有顯示編輯器區(qū)域。是通過修改ApplicationWorkbenchWindowAdvisor.java和Perspective.jave文件實(shí)現(xiàn)的,如下圖:




      怎么在plugin.xml中通過Extension來顯示這兩個(gè)視圖,我就不截圖了。下面來看怎么定義菜單。下面是定義完Commands、Bindings和Menus的界面


      可以看到,locationURI使用的是menu:org.eclipse.ui.main.menu?after=additions,就是把菜單添加到主窗口的菜單欄中。

      下面是定義完菜單程序的運(yùn)行效果,因?yàn)闆]有實(shí)現(xiàn)Handler,所以菜單項(xiàng)顯示為灰色:



      下面,來實(shí)現(xiàn)Handler。首先實(shí)現(xiàn)顯示Bundles的功能。在上一篇中我講過,Bundles是OSGi的概念,如果想知道我們的程序有哪些Bundles,可以通過Activator的start方法的context參數(shù)得到。所以,我們先改寫Activator類,在里面添加一個(gè)static的List<String>,在start方法中獲取所有的bundles,并將它們的SymbolicName保存到List<String>中,如下圖:



      然后,添加一個(gè)ShowBundlesHandler類,繼承自org.eclipse.core.commands.AbstractHandler,代碼很簡(jiǎn)單,如下:


      在plugin.xml中定義org.eclipse.ui.handlers擴(kuò)展,如下圖:


      再來實(shí)現(xiàn)另外一個(gè)菜單項(xiàng)的功能。先添加一個(gè)ShowExtensionsHandler類,仍然繼承自org.eclipse.core.commands.AbstractHandler。代碼如下:

      以上代碼展示了怎么使用Platform類來獲得所有的擴(kuò)展點(diǎn)和擴(kuò)展。同時(shí)也展示了SWT的Tree控件使用起來也很簡(jiǎn)單。
      下面是程序的運(yùn)行效果:


    補(bǔ)充內(nèi)容:
      Eclipse在Ubuntu下的表現(xiàn)并不完美,甚至有些Bug讓我走了不少彎路。
      Eclipse在Ubuntu中的菜單項(xiàng)是不能顯示圖標(biāo)的,如下兩圖,左邊是Ubuntu中Eclipse的菜單,沒有圖標(biāo),右邊是Win7中的菜單,有圖標(biāo):(同樣的Eclipse 3.8.1版)
      

      更坑爹的是,Ubuntu中的RCP程序經(jīng)常不顯示菜單欄,只有顯示Splash Screen的程序才能正常顯示菜單欄。如下兩圖,都是用Eclipse自帶的向?qū)傻某绦颍琔buntu中沒有菜單欄,Win7中有:
      

      所以,我上面的示例程序并不是從Hello RCP模板擴(kuò)展而來的,而是從RCP Mail Template創(chuàng)建,然后刪掉不要的功能,再然后擴(kuò)展而來的。如下圖:


    下一篇:
    Eclipse RCP詳解(03):SWT的相關(guān)概念以及一個(gè)連連看游戲的實(shí)現(xiàn)

    評(píng)論

    # re: Eclipse RCP詳解(02):Eclipse的Runtime和UI初探  回復(fù)  更多評(píng)論   

    2014-01-25 06:40 by 魏五鎖業(yè)
    給力支持博主。。。。。。互訪哦

    # re: Eclipse RCP詳解(02):Eclipse的Runtime和UI初探  回復(fù)  更多評(píng)論   

    2014-01-26 06:40 by 零柒鎖業(yè)
    互相學(xué)習(xí)學(xué)習(xí),歡迎回訪

    # re: Eclipse RCP詳解(02):Eclipse的Runtime和UI初探  回復(fù)  更多評(píng)論   

    2014-01-27 06:41 by 零柒鎖業(yè)
    喜歡新鮮的事物~歡迎回訪

    # re: Eclipse RCP詳解(02):Eclipse的Runtime和UI初探  回復(fù)  更多評(píng)論   

    2014-12-21 00:43 by 當(dāng)當(dāng)爸
    你好,請(qǐng)問我在org.eclipse.ui.bindings擴(kuò)展里添加了快捷鍵綁定,為什么運(yùn)行后沒有綁定成功,菜單里文字后面根本沒有顯示快捷鍵?

    # re: Eclipse RCP詳解(02):Eclipse的Runtime和UI初探  回復(fù)  更多評(píng)論   

    2014-12-21 00:57 by 當(dāng)當(dāng)爸
    解決了,原來是因?yàn)閟chemeId用了自己新建的沒用org.eclipse.ui.defaultAcceleratorConfiguration。
    另外org.eclipse.ui.menus里可以設(shè)置command的圖片,org.eclipse.ui.commandImages這個(gè)擴(kuò)展點(diǎn)是不是一般都不用?
    主站蜘蛛池模板: 久久夜色精品国产噜噜噜亚洲AV| a级大片免费观看| 精品日韩亚洲AV无码一区二区三区| 免费无码又爽又刺激高潮的视频| 99久9在线|免费| 国产精品极品美女自在线观看免费 | 久久九九全国免费| 亚洲av无码专区在线观看亚| 久久水蜜桃亚洲av无码精品麻豆| 亚洲欧洲自拍拍偷精品 美利坚| 成年人免费网站在线观看| 亚洲视频在线免费观看| 九九热久久免费视频| 美女免费视频一区二区三区| 国产成人亚洲综合一区| 亚洲国产成+人+综合| 91嫩草私人成人亚洲影院| 国产偷v国产偷v亚洲高清| 亚洲中文字幕无码一久久区| 日本中文一区二区三区亚洲| 麻豆国产入口在线观看免费| 妞干网免费观看视频| 无码国产精品久久一区免费| 亚洲精品在线免费看| 最近免费中文字幕mv在线电影| 久久精品一区二区免费看| 久久久久久久99精品免费观看| 国产精品高清免费网站| xvideos永久免费入口| 无码的免费不卡毛片视频 | 国产男女爽爽爽爽爽免费视频| 久久国产乱子伦精品免费一| 在线观看免费黄网站| 青青操视频在线免费观看| 两个人看www免费视频| 青柠影视在线观看免费高清| 国产在线国偷精品免费看| 国产免费久久久久久无码| caoporm碰最新免费公开视频| www一区二区www免费| 免费看一区二区三区四区|