用Eclipse做Java开发的朋友应该知道SWT中下拉列表框Combo。
在SWT自定义控件中,引入了CCombo,它也实现了Combo的功能。与Combo不同的是,它不是系统的native控件,而是通过Text、Button、List、Shell这几个控件组合而成的,不过用起来可能与Combo并没有什么不同。
问题提出
在Eclipse BIRT中,有这样的功能:
打开New Map Rule对话框,如下图所示,右边用记号标出来的区域,当用户点击倒三角符号时,下拉菜单会出现
如果用户选中其中的某一个值,点“OK”,它的值就会返回到Combo中去。
在实现这个功能的时候,我曾经试图给Combo加几个简单Listener来实现这样的功能。后来发现在不同的平台上,由于系统实现不一样,Linux或者Mac机上或多或少存在一些问题。于是,我给SWT发过bug:224837、210908,希望SWT组能够让Combo在Linux和MacOS下能够像windows下一样正常工作。但他们迟迟没有修正,我不知道是不是平台不同,行为就不同。或许这种行为就是期望中的吧。
如何解决
既然SWT不愿意修正,那就只能自己动手、丰衣足食了。
要实现如上的功能,我有两种方法:
1.封装Combo:把Combo的各种Listener进行封装,用一个新的class来管理Combo;
2.改进CCombo:修改CCombo的代码,已达到改进的目的。
封装Combo
先讲述如何封装Combo已达到所需的目标。
由于Combo是平台相关的,不同的平台上,底层的实现是不一样的,因此我只能封装Combo,而不能改变Combo的内部实现,否则很难保证它能够真正的实现跨平台。
在此,我通过创建一个新的class继承Combo,封装Combo的各种listener,部分代码如下:
public class ValueCombo extends Combo
{
public static interface ISelection
{
public String[] doSelection( String input );
}// add SelectionListener is forbidden, please use addSelectionListener(index
// , selection) instead.
public void addSelectionListener( SelectionListener listener )
{
// do nothing
}// add KeyListener is forbidden
public void addKeyListener( KeyListener listener )
{
// do nothing
}public void addListener( int eventType, Listener listener )
{
if ( addListenerLock == true
&& ( eventType == SWT.Selection || eventType == SWT.KeyUp || eventType == SWT.KeyDown ) )
{
return;
}
super.addListener( eventType, listener );
}// index : [0, getItemCount – 1]
public void addSelectionListener( int index, ISelection selection )
{
actionMap.put( index, selection );
}// index : [0, getItemCount – 1]
public void removeSelectionListener( int index )
{
actionMap.remove( index );
}………………
}
ValueCombo封装了Combo,用户可以通过接口 public void addListener( int eventType, Listener listener )给ValueCombo添加事件,事件类型可以是除SWT.Selection、SWT.KeyUp和SWT.KeyDown之外Combo支持的所有事件。
从实现来看,用户无法通过API添加SWT.Selection、SWT.KeyUp和SWT.KeyDown这三种类型的事件。是为什么禁止用户添加这三种类型的事件呢?因为在内部的逻辑处理过程中,我们必须用到这三种类型事件,为了防止用户添加事件而破坏内部的逻辑,这也是不得已而为之。
但是,当用户选中ValueCombo中的一个item的时候,我们的确希望触发某些事件,那该怎么做呢?为此,我准备了ISelection.doSelection(String input)这个接口,用它来代替AddSelectionListener()。
更多内容,可以参见代码和示例。
修改CCombo
SWT中引入了CCombo,它不是系统native widget,而是通过几个native widget组合而成的,使用起来与native widget稍许有些差异。
这儿,我写了一个CCombo,原封不动的把SWT的CCombo拷贝过来之后,稍微作了一点修改。
加入了一个变量 boolean selEvent。如果selEvent为true,当用户选中CCombo中的某个item,item的值并不会马上填充到text框中。
代码示例
这儿,我共享了所有的代码和示例。
对源代码感兴趣的朋友点击<<此处>>下载。你也可以完全免费使用它,不过你必须遵循Eclipse Public License v1.0。如果你发现它有什么缺陷,或者有好的改进方法,欢迎与我联系。
(完)
请你留言