eclipshine

          Eclipse主題站

          RCP中視圖間的交互機(jī)制探討

          有時(shí)候一個(gè)視圖(View)希望得到另外一個(gè)視圖顯示的內(nèi)容,或者選擇的內(nèi)容。在Eclipse中,比較標(biāo)準(zhǔn)的做法是通過(guò)ISelectionProviderISelectionListener來(lái)完成的。不過(guò)因?yàn)橐晥D往往是獨(dú)立的,他們之間并不太方便進(jìn)行直接的事件監(jiān)聽(tīng),而且往往一個(gè)視圖需要對(duì)諸多試圖進(jìn)行選擇事件的監(jiān)聽(tīng),因此在這種情況下對(duì)每一個(gè)視圖的事件進(jìn)行注冊(cè),比較繁瑣,有時(shí)候也不可能(比如在需要被監(jiān)聽(tīng)的試圖尚未激活的情況下)。

          比較典型的例子就是Eclipse本身所提供的PropertySheetOutline這兩個(gè)視圖,他們都是對(duì)其它試圖或者Editor中的選擇進(jìn)行監(jiān)聽(tīng),并更具選擇的內(nèi)容作相應(yīng)的處理,顯示其Outline或者屬性頁(yè)。

           Eclipse為了解決這個(gè)問(wèn)題,提供了所謂的Site,以及ISelectionService機(jī)制,來(lái)處理試圖之間的簡(jiǎn)單的交互。簡(jiǎn)單的說(shuō),ViewSite提供了一個(gè)交互的中心點(diǎn),其它ViewViewSite提供選擇事件,或者向其注冊(cè)監(jiān)聽(tīng)器,而事件的觸發(fā)與轉(zhuǎn)發(fā)則由ViewSite()來(lái)完成。

          這應(yīng)該也是一個(gè)設(shè)計(jì)模式,不過(guò)我還沒(méi)想到比較接近的設(shè)計(jì)模式的名字。如果勉強(qiáng)要使用一個(gè)的話,我認(rèn)為“Mediator”(調(diào)停者模式)可能比較適合(歡迎發(fā)表見(jiàn)解) 

          調(diào)停者模式
          Blabla...

          為了在這個(gè)機(jī)制中扮演角色,視圖通常需要實(shí)現(xiàn)兩類接口,或者Adapter。首先是作為被監(jiān)聽(tīng)方的視圖,需要實(shí)現(xiàn)ISelectionProvider接口。ISelectionProviderJface中引入的接口。

                 public interface ISelectionProvider {

                     public void addSelectionChangedListener(ISelectionChangedListener listener);

                     public ISelection getSelection();

                     public void removeSelectionChangedListener(

                             ISelectionChangedListener listener);

                     public void setSelection(ISelection selection);

                 }

          方法都比較簡(jiǎn)單,不做一一闡述。具體實(shí)現(xiàn)時(shí),可能需要進(jìn)行所謂的hookControl,也就是將View中具體控件的事件,關(guān)聯(lián)到這個(gè)View所提供的ISelectionProvider上,簡(jiǎn)單的一個(gè)例子,如果View中控件是一個(gè)TableViewer的話,那么可以做如下的操作:

                 protected void hookControl(Control control) {

                 tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){

                        public void selectionChanged(SelectionChangedEvent event) {

                               ISelection selection2 = event.getSelection();

                               setSelection(selection2);

                        }

                 });

                 }

           

          然后再setSelection()中對(duì)事件進(jìn)行擴(kuò)散(propagate

                 public void setSelection(ISelection selection) {

                        this.selection = selection;

                        SelectionChangedEvent event2 = new SelectionChangedEvent(

                                      OntIndividualEditor.this, selection);

                        for (Iterator i = selectionChangeListeners.iterator(); i.hasNext();) {

                               ISelectionChangedListener object = (ISelectionChangedListener) i

                                             .next();

                               object.selectionChanged(event2);

                        }

                 }

           

          一個(gè)ISelectionProvider如果希望被別的View進(jìn)行監(jiān)聽(tīng)的話,則應(yīng)該向其Site()進(jìn)行注冊(cè):

                 this.getSite().setSelectionProvider(this);

          如果事件比較簡(jiǎn)單,比如上面的例子,只是對(duì)TableViewer的選擇進(jìn)行監(jiān)聽(tīng),因?yàn)?/span>TableViewer本身就是一個(gè)ISelectionProvider,因此可以直接這樣做:

                 this.getSite().setSelectionProvider(tableViewer);

          這樣View本身就不必實(shí)現(xiàn)ISelectionProvider接口了,但是實(shí)現(xiàn)的效果同上面的方式實(shí)現(xiàn)的是一樣的。

           作為事件監(jiān)聽(tīng)的另一端,則更為簡(jiǎn)單一些。只需要實(shí)現(xiàn)ISelectionListener接口,并注冊(cè)在Site中:

                 site.getPage().addSelectionListener(this);

          然后實(shí)現(xiàn)public void selectionChanged(IWorkbenchPart part, ISelection selection) {}方法即可。這樣,當(dāng)SelectionProvider中的選擇發(fā)生改變時(shí),這個(gè)視圖中的selectionChanged()方法就會(huì)被調(diào)用。

           注意SelectionProviderSelectionListener并不直接對(duì)應(yīng)。這個(gè)地方有一點(diǎn)容易混淆,就是Eclipse實(shí)際上提供有兩套與Selection相關(guān)的事件與接口:

          ISelectionChangedListener <--> ISelectionProvider

          這個(gè)是JFace中的選擇監(jiān)聽(tīng)機(jī)制,對(duì)試圖或者控件而言,它提供對(duì)原始的選擇事件的通知與響應(yīng)。ISelectionProvider需要注冊(cè)在Site上,以供ISelectionSerivce使用,將選擇事件擴(kuò)散到其他的ISelectionListener中。

          ISelectionListener <--> ISelectionService

          這個(gè)是在Site中使用的,ISelectionService不需要自己實(shí)現(xiàn),已經(jīng)實(shí)現(xiàn)好了,ISelectionListener則需要注冊(cè)到ISelectionService上,以對(duì)其它SelectionProvider的事件響應(yīng)進(jìn)行監(jiān)聽(tīng)。

           Eclipse本身的實(shí)現(xiàn)中,PropertySheetOutline都使用了這種機(jī)制。不過(guò)需要注意的是,缺省的PropertyShee需要接受一個(gè)IStructuredSelection,而不僅僅是一個(gè)ISelection。因此,如果ISeletionProvider需要提供一個(gè)能夠讓PropertySheet進(jìn)行顯示的對(duì)象的話,除了除了要實(shí)現(xiàn)ISelection接口外,還需要對(duì)其進(jìn)行封裝成一個(gè)IStructuredSelection。這個(gè)比較簡(jiǎn)單,直接調(diào)用StructuredSelection構(gòu)造函數(shù)即可。

          posted on 2005-09-19 22:42 Living Not Striving 閱讀(5094) 評(píng)論(6)  編輯  收藏 所屬分類: RCPECLIPSE

          評(píng)論

          # re: RCP中視圖間的交互機(jī)制探討 2005-09-19 22:43 eclipshine

          得八進(jìn)制勉勵(lì),新發(fā)一篇:)  回復(fù)  更多評(píng)論   

          # re: RCP中視圖間的交互機(jī)制探討 2005-09-20 16:20 Dart

          好文章!一直以來(lái),我都是傳遞View本身對(duì)象來(lái)實(shí)現(xiàn)事件監(jiān)聽(tīng),原來(lái)利用SelectionService中轉(zhuǎn)可以實(shí)現(xiàn)啊。
          謝謝樓主的文章!  回復(fù)  更多評(píng)論   

          # re: RCP中視圖間的交互機(jī)制探討 2005-09-20 16:46 eclipshine

          傳遞View本身會(huì)有一些問(wèn)題,需要有特定的視圖激活的順序才行。
          不過(guò)那樣做也有好處,因?yàn)槭录D(zhuǎn)發(fā)更為特定,因此可以提高系統(tǒng)性能。

          而本文中所描述的方法,則當(dāng)任何視圖上的任何選擇事件發(fā)生時(shí),任何監(jiān)聽(tīng)者都會(huì)得到通知,系統(tǒng)性能會(huì)有一定的影響。  回復(fù)  更多評(píng)論   

          # re: RCP中視圖間的交互機(jī)制探討 2005-09-20 22:28 gady

          呵呵 我也是傳view的 看了這篇文章,我忽然發(fā)現(xiàn)eclipse中的action是不是也是這樣做的 對(duì)于右鍵菜單中的action一般要實(shí)現(xiàn)一個(gè)checkEnable方法?  回復(fù)  更多評(píng)論   

          # re: RCP中視圖間的交互機(jī)制探討 2005-11-08 10:41 witty_wang

          selectionChangeListeners是所有監(jiān)聽(tīng)器列表嗎?如何獲得這個(gè)對(duì)象阿?  回復(fù)  更多評(píng)論   

          # re: RCP中視圖間的交互機(jī)制探討[未登錄](méi) 2008-10-28 21:19 fish

          Mediator和Observer模式。  回復(fù)  更多評(píng)論   

          主站蜘蛛池模板: 大安市| 西华县| 衡东县| 彩票| 祁门县| 吉木萨尔县| 龙游县| 克拉玛依市| 九台市| 大丰市| 本溪市| 璧山县| 贵南县| 合肥市| 平利县| 饶平县| 从江县| 桂林市| 阿拉善右旗| 南乐县| 黑龙江省| 张北县| 晋宁县| 中牟县| 侯马市| 横山县| 洛阳市| 留坝县| 大田县| 瑞丽市| 吕梁市| 临湘市| 临猗县| 漯河市| 剑川县| 姚安县| 天峻县| 改则县| 和硕县| 尉犁县| 库车县|