监听在一个特定的Viewer中的进行的选择是RCP开发中经常遇到的情况。例如,在TabelViewer中或TreeViewer中用户选择了一行数据或者一个节点时,需要针对当前的Selection做出某些处理(如更新Text组件中的数据)。
图1. Selection Provider和Listener在同一视图中
为了方便对此机制的介绍,我们设定一个如图1中所示的场景,当用户在视图左边的TabelViewer中选择一个节点后,在右边的Text Component中将显示出所选择的内容。
在RCP的开发中,我们可以基于实际情况的不同,采取以下的办法:
1. 直接调用Viewer的addSelectionChangedListener方法
2. 使用Selection Provider-Selection Listener机制
此两种方法,各自有优缺点及适用的范围,以下将分别对其说明。
直接调用Viewer的addSelectionChangedListener方法
这种方法是最简单明了的,它只需要在Viewer的addSelectionChangedListener方法中实现一个Listener即可。但它只适用于Viewer和Listener在同一个视图中的情况下,如图1所示。也就是说,如果我们的Viewer和Text Component在同一个视图中,可以使用一个Listener监听在同一个视图中发生的Selection变化。
实现的过程如下:
a. 定义并初始化一个Viewer。
b. 在Viewer的addSelectionChangedListener方法中定义一个Listner。
c. 在Listner中实现对UI Component的数据更新。
使用Selection Provider-Selection Listener机制
这种机制是在实践中最经常用到的,特别是用在Selection发生的视图和Listener所在的视图不相同的情况下(如图2所示)。虽然所在视图不相同,但他们都处于一个相同的WorkbenchPage中。在这种方法中,我们需要首先定义一个Selection的Provider,即谁提供这个Selection Event,本例中当然是Viewer。然后,我们需要生成一个Listener用来处理Selection Event。而Provider和Listener之间的关联,可以通过由当前WorkbenchPage管理的Listener注册器完成。即将我们的Listener注册到这个注册器中,一旦当前WorkbenchPage的SelectionProvider发出SelectionChangedEvent时,所有注册的Listener就可以做出相应的处理。
图2. Selection Provider和Listener在不同的视图中
实现的过程如下:
a. 在视图1中定义并初始化一个Viewer。
b. 在视图1中定义Viewer为SelectionProvider。
c. 在同一WorkbenchPage中的视图2中定义一个ISelectionListener,为了方便处理视图内的UI Component,通常在视图中实现此接口。
d. 实现ISelectionListener的方法selectionChanged,用于处理Selection变化。
e. 将实现了ISelectionListener的Listener(通常就是视图自己)注册到当前WorkbenchPage管理的Listener注册器。
此方法需要注意的是,在同一个视图中只能定义一个SelectionProvider,但针对此Provider可以在不同的视图中注册多个Listener。相反,一个已注册的Listener可以同时监听,来自不同视图的SelectionProvider发出的SelectionChangedEvent。为了进一步限制监听的对象,可以在注册时指定监听的视图。
这样,SelectionListener只监听来自SampleView的SelectionChangedEvent。
总结
在常规的RCP开发中,处理Selection监听的任务,通过上述的两种方法可以轻松的完成。若Selection的Provider和Listener都在一个视图,且只需要简单处理SelectionChangedEvent时,我们可以选择方法1即可。若Selection的Provider和Listener分散在两个或多个视图时,我们必须通过方法2完成。当然,对于在同一视图的情况,我们也可以通过方法2实现,原理也是一样的。另外,其他较为复杂的Selection Provider-Listener的情况,还可以使用RCP的IAdaptable实现。