SWT高级主题(Standard Widget Toolkit)第一部分
在SWT基础中,我们简要的了解了SWT的产生背景,开发SWT应用程序的基本要求以及基本的SWT组件以及部分事件监听器。本部分内容将介绍一些高级的组件,布局管理器等高级主题。
高级组件:
Tables:Table组件用于显示图片或者字符串的列表,并且在被选择的时候可以弹出提示。
Table table1 = new Table(shell, SWT.BORDER);
可选的样式包括:BORDER,H_SCROLL,V_SCROLL,SINGLE,MULTI,CHECK(在第一列产生checkbox列),FULL_SELECTION和HIDE_SELECTION。VITURAL创建的table的TableItems可以很大的提高性能。
可以设置table中的线以及table的header是否可见,默认的设置都是false。虽然这个类也是Composite的子类,但是为其添加Control,或者为其设置Layout是没有意义的,除非实现像cell编辑器一样的东西。
Table创建完成后,默认只有一列,如果要追加内容,只有每行的第一列会被显示,为了显示所有的field,需要定义TableColumns。
TableColumn:将TableColumn追加到Table的方法如下:
TableColumn name = new TableColumn(table, SWT.LEFT);
可选的样式包括LEFT,RIGHT,CENTER.
同时至少要设置column的宽度,如果要显示header的话,还需要设置名字。
name.setText("Name");
name.setWidth(50);
创建完Table的列之后,就可以添加TableItems了。
TableItem:通过下面的语句将TableItem追加到Table中。
TableItem item1 = new TableItem(table,SWT.NONE);
没有什么适用于TableItem的样式,所以设置为SWT.NONE。
可以使用item1.setText(String[])或者item1.setText(int, String)的方式来填充TableItem。如果Table的style不是FULL_SELECTION,那么只有第一列是可选的,即鼠标选中时有反应,而其他的field是不可选择的。
TabFolder:用于实现像笔记本一样的功能,用户可以选择任意一个tab。
TabFolder tabFolder = new TabFolder(shell,SWT.NONE);
支持TabFolder的style有TOP,BOTTOM。虽然该类是Composite的子类,但是对它设置layout是没有意义的。
可以通过以下的方式创建TabItem:
TabItem item1 = new TabItem(tabFolder,SWT.NONE);
没有可用的样式。创建tab item有两个步骤,首先,创建tab上面的label,可以通过setText方法设置。然后,为了显示tab item,需要设置它包含的control,通过setControl方法:
item1.setText("Buttons");
item1.setControl(buttonComp);
在上面的例子中,buttonComp是一个Composite,每个tab item中只可以放一个control,所以一般来说必须是一个Composite,这样才可以包含其他的组件。事件处理已经内置到TabItem和TabFolder中。
TabFolder tabFolder1 = new TabFolder(shell,SWT.NONE);
tabFolder1.setBounds(10,10,270,250);
//Set up the button tab
Composite buttonComp = new Composite(tabFolder1,SWT.NONE);
Button button1 = new Button(buttonComp,SWT.PUSH);
button1.setSize(100,100);
button1.setText("Hello");
button1.setLocation(0,0);
Button button2 = new Button(buttonComp,SWT.ARROW);
button2.setBounds(150,0,50,50);
TabItem item1 = new TabItem(tabFolder1,SWT.NONE);
item1.setText("Buttons");
item1.setControl(buttonComp);
Slider,Scale,Progress Bar:滑块,调节器和进度条是非常相似的控件。但是它们使用一些不同的方法来正常的工作。
Slider slider1 = new Slider(shell, SWT.HORIZONTAL);
Scale scale1 = new Scale(shell, SWT.HORIZONTAL);
适用于Slider和Scale的样式包括:BORDER,HORIZONTAL和VERTICAL.可以通过方法设置最大值和最小值:
slider1.setMaximum(100);
slider1.setMinimum(0);
可以通过slider.setSelection(50);来确定滑块或者标记的位置。如前所示,滑块的左侧将会位于整个区域的中间。如果是Slider的话,还可以设置滑块的大小。slider.setThumb(30);对于Scale,可以设置页面的增量,来确定测量条放在scale上的个数。通过使用scale.setPageIncrement(50);来进行设置。
Slider slider1 = new Slider(shell, SWT.HORIZONTAL);
slider1.setBounds(0,0,200,20);
slider1.setSelection(50);
slider1.setMaximum(100);
slider1.setMinimum(0);
slider1.setThumb(30);
Scale scale1 = new Scale(shell, SWT.HORIZONTAL);
scale1.setBounds(0,40,200,40);
scale1.setMinimum(0);
scale1.setMaximum(500);
scale1.setSelection(100);
scale1.setPageIncrement(50);
可以通过下面的代码来创建一个进度条:
ProgressBar progressBar1 = new ProgressBar(shell,SWT.HORIZONTAL);
可以使用的样式包括BORDER、VERTICAL、HORIZONTAL。也可以使用SMOOTH,返回一个平滑的bar。对于进度条来说,可以设置最大,最小值和选择位置。选择位置基于最小值和最大值,和slider不同,不可以设置进度条的进度提示条的宽度。
ProgressBar progressBar1 = new ProgressBar(shell,SWT.HORIZONTAL);
progressBar1.setMinimum(0);
progressBar1.setMaximum(100);
progressBar1.setSelection(30);
progressBar1.setBounds(10,10,250,20);
菜单和菜单项:菜单可以包含子菜单,快捷键,事件处理以及不同的菜单项。通过使用Menu和MenuItem组件来设置菜单。可以通过下面的代码在shell的顶部创建菜单区域:
Menu menu = new Menu(shell, SWT.BAR);
shell.setMenuBar(menu);
菜单栏的样式必须为SWT.BAR。可用的样式包括:BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP,LEFT_TO_RIGHT, RIGHT_TO_LEFT。
Note: Only one of BAR, DROP_DOWN and POP_UP may be specified. Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
下面向Menu中添加一个MenuItem。
MenuItem file = new MenuItem(menu,SWT.CASCADE);
fule.setText(“File”);
添加完成之后,可以看到在shell的顶部的菜单栏中,包含一个File菜单,点击之后,没有任何的反应,确保样式是SWT.CASCADE,即级联菜单,这样才会弹出下拉菜单。
接下来可以向File选项中追加菜单:
Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);
file.setMenu(fileMenu);
最后,可以将菜单项添加到菜单中:
MenuItem actionItem = new MenuItem(fileMenu, SWT.PUSH);
actionItem.setText(“Action”);
至此,已经创建了一个包含可以选择项目的文件菜单。为了提示选项被选择,可以为菜单项追加事件监听器:
actionItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Action performed!");
}
});
继续一个更复杂一些的例子,首先MenuItem的样式不再是PUSH,可选的样式包括CHECK,RADIO,SEPARATOR,CASCADE。分别表示复选框,单选按钮,分隔符。
MenuItem separator = new MenuItem(filemenu, SWT.SEPARATOR);
final MenuItem radioItem = new MenuItem(filemenu, SWT.RADIO);
radioItem.setText("Radio");
final MenuItem checkItem = new MenuItem(filemenu, SWT.CHECK);
checkItem.setText("Check");
下面的代码为单选按钮和复选框追加了事件监听器:
radioItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Radio item toggled to:"+
radioItem.getSelection());
}
});
checkItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Check item toggled to:" +
checkItem.getSelection());
}
});
下面通过和创建菜单一样的方式创建子菜单:
MenuItem cascadeItem = new MenuItem(filemenu, SWT.CASCADE);
cascadeItem.setText("Cascade");
Menu submenu = new Menu(shell, SWT.DROP_DOWN);
cascadeItem.setMenu(submenu);
然后为子菜单追加菜单项,新追加的菜单项叫做SubAction。注意,在设置标题的时候,在字符S前面使用了&符号,表示助记符。当子菜单被现实的时候,可以通过按下S键,选择该菜单项。然后通过setAccelerator来为SubAction设置快捷键,为CTRL+S。此时用户可以不需要打开菜单就可以执行该操作。
final MenuItem subactionItem = new MenuItem(submenu, SWT.PUSH);
subactionItem.setText("&SubAction/tCtrl+S");
subactionItem.setAccelerator(SWT.CTRL+'S');
然后追加一个用来显示是否启用菜单项的子菜单选项:
final MenuItem enableItem = new MenuItem(submenu, SWT.CHECK);
enableItem.setText("Enable SubAction");
有很多可用的监听器,下面只举个简单的例子,子菜单显示和隐藏时的事件处理:
submenu.addMenuListener(new MenuListener() {
public void menuShown(MenuEvent e) {
System.out.println("SubMenu shown");
}
public void menuHidden(MenuEvent e) {
System.out.println("SubMenu hidden");
}
});
可以通过以下的方式来禁用或者启用菜单项:
subactionItem.setEnabled(false);
enableItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Toggling /"Enable SubAction/" to "
+ enableItem.getSelection());
subactionItem.setEnabled(enableItem.getSelection());
}
});
还可以直接使用SelectionListener:
subactionItem.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
System.out.println("SubAction performed!");
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
另外一个事件监听器就是ArmListener,当菜单项被选中,高亮显示时,但是还没有选择(鼠标点击或者按下回车键)时,触发该事件。
subactionItem.addArmListener(new ArmListener() {
public void widgetArmed(ArmEvent e) {
System.out.println("SubAction armed!");
}
});
还有一个监听器就是帮助监听器HelpListener,通过按下F1/Help键,HelpListener被触发。可以用来提供帮助信息。
subactionItem.addHelpListener(new HelpListener() {
public void helpRequested(HelpEvent e) {
System.out.println("Help requested on SubAction");
}
});
弹出菜单:弹出式菜单对于屏幕不同区域的上下文菜单很有用,这样用户就可以不用去屏幕顶部的菜单栏去找菜单项了。通过右键点击具有上下文关联菜单的Composite,可以在鼠标边上悬浮菜单,允许用户选择菜单项。
和之前一样,创建一个菜单,将菜单的样式设置为SWT.POP_UP,然后为其添加一个item,然后添加一个事件监听器来监听选择时间,这就是shell和composite的菜单:
Menu popupmenu = new Menu(shell, SWT.POP_UP);
MenuItem actionItem1 = new MenuItem(popupmenu, SWT.PUSH);
actionItem1.setText("Other Action");
actionItem1.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Other Action performed!");
}
});
Menu popupmenu2 = new Menu(shell, SWT.POP_UP);
MenuItem buttonItem = new MenuItem(popupmenu2, SWT.PUSH);
buttonItem.setText("Button Action");
buttonItem.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
System.out.println("Button Action performed!");
}
});
下面创建一个composite和button,将其添加到shell上,然后为button,composite和shell设置弹出菜单:
Composite c1 = new Composite(shell, SWT.BORDER);
c1.setSize(100, 100);
c1.setLocation(25, 25);
Button b = new Button(c1, SWT.PUSH);
b.setText("Button");
b.setSize(50, 50);
b.setLocation(25, 25);
b.setMenu(popupmenu2);
c1.setMenu (popupmenu);
shell.setMenu (popupmenu);
同样,右键菜单可以有子菜单,单选按钮,事件监听器等等功能。
树:树结构用来显示层状结构的信息,例如显示文件夹和子文件夹,类和子类等。创建树的样式可以是SWT.MULTI,SWT.SINGLE,SWT.CHECK. SINGLE只允许选中树中的一个项目,MULTI可以选择多个。同时只能指定两者中的一个。CHECK为树的每个选项增加复选框。例如Eclipse使用CHECK样式的tree来选择将哪些文件导入/导出。
final Tree tree = new Tree(shell, SWT.MULTI | SWT.BORDER);
tree.setSize(150, 150);
tree.setLocation(5,5);
上面的代码创建了一个简单的没有枝干和叶子的树,允许多选并且带有边框。通过添加TreeItem来为树添加内容。首先创建树根。
TreeItem myComp = new TreeItem(tree, SWT.NONE);
myComp.setText("My Computer");
TreeItem netPlaces = new TreeItem(tree, SWT.NONE);
netPlaces.setText("My Network Places");
TreeItem myDocs = new TreeItem(tree, SWT.NONE, 1);
myDocs.setText("My Documents");
第三个参数表示TreeItem的位置。上面的代码中,My Documents节点位于中间。
通过使用相同的构造器来创建TreeItem的子节点。
TreeItem hardDisk = new TreeItem(myComp, SWT.NONE);
hardDisk.setText("Local Disk (C:)");
TreeItem floppy = new TreeItem(myComp, SWT.NONE, 0);
floppy.setText("3.5 Floppy (A:)");
可以持续的这样创建下去。例如为磁盘C再创建子节点:
TreeItem progFiles = new TreeItem(hardDisk, SWT.NONE);
progFiles.setText("Program Files");
同时,还可以为TreeItem添加图片:
Image icon = new Image(display, "arrow.jpg");
progFiles.setImage(icon);
还可以为树追加事件监听器,事件监听器是和整个树对象关联在一起的。但是用SelectionListener时,getSelection()返回的是选中的树的TreeItem的列表。还可以监听树的合起与打开事件:
tree.addTreeListener(new TreeListener() {
public void treeCollapsed(TreeEvent e) {
System.out.println("Tree collapsed.");
}
public void treeExpanded(TreeEvent e) {
System.out.println("Tree expanded.");
}
});
其中TreeEvent具有item属性,表示选中的item。
如果树的样式为CHECK,那么还可以通过调用getChecked方法来判断TreeItem是否被选中。
工具栏:工具栏可以为经常使用的任务提供快捷方式,而不是使用复杂的菜单。工具栏上面的按钮和标准的按钮的样子基本相同,只是他们以分组的方式显示在工具栏中,并且可以同时包含文本和图片。
final ToolBar bar = new ToolBar(shell,SWT.HORIZONTAL);
bar.setSize(380,150);
bar.setLocation(10,10);
为了将图片添加到一些按钮上,必须将图片加载。
Image icon = new Image(display,”arrow.bmp”);
接下来初始化三个Tool项目。每个都是一个简单的压下式按钮。
ToolItem pushItem1 = new ToolItem(bar, SWT.PUSH);
pushItem1.setText("Push");
ToolItem pushItem2 = new ToolItem(bar, SWT.PUSH);
pushItem2.setImage(icon);
ToolItem pushItem3 = new ToolItem(bar, SWT.PUSH);
pushItem3.setText("Push");
pushItem3.setImage(icon);
上面的代码创建三个ToolItem,其中分别包含了文字,图片,图片和文字。图片位于文字上方。
还可以创建一个SEPARATOR样式的可见分割条。
ToolItem sep = new ToolItem(bar, SWT.SEPARATOR);
同样可以包含CHECK和RADIO的按钮。
ToolItem checkItem = new ToolItem(bar, SWT.CHECK);
checkItem.setText("Check");
new ToolItem(bar, SWT.SEPARATOR);
ToolItem radioItem1 = new ToolItem(bar, SWT.RADIO);
radioItem1.setText("Radio 1");
ToolItem radioItem2 = new ToolItem(bar, SWT.RADIO);
radioItem2.setText("Radio 2");
new ToolItem(bar, SWT.SEPARATOR);
ToolItem radioItem3 = new ToolItem(bar, SWT.RADIO);
radioItem3.setText("Radio 3");
ToolItem radioItem4 = new ToolItem(bar, SWT.RADIO);
radioItem4.setText("Radio 4");
上面的代码有两处需要注意:一,单选按钮的行为是自动完成的,即上面的单选按钮1和2,3和4自动编成组,即1和2只能选中一个,3和4只能选中一个。(在菜单中的这个功能必须手动编成完成)。二,一中描述的功能当前仅当两个radio按钮紧挨着时。
最后一种ToolItem是下拉式的按钮。左侧按钮和标准的按钮一样,右侧包含了一个下拉式的箭头来提示包含下拉菜单。为了将下拉菜单和其绑定,必须捕获selection事件,然后使用SelectionEvent的x和y坐标来决定在哪里弹出菜单。
final ToolItem dropdown = new ToolItem(bar, SWT.DROP_DOWN);
dropdown.setText("Drop-down");
final Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem choice = new MenuItem(menu, SWT.PUSH);
choice.setText("Choices");
dropdown.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.ARROW) {
Rectangle rect = dropdown.getBounds();
Point pt = new Point(rect.x, rect.y + rect.height);
pt = bar.toDisplay(pt);
menu.setLocation(pt.x, pt.y);
menu.setVisible(true);
}
}
});
CoolBar:CoolBar可以创建和工具栏一样的元素,只是可以动态的由用户摆放。例如Eclipse顶部的工具栏。可以拖放在任意的位置。类似的CoolBar还出现在Word以及IE中。
final CoolBar bar = new CoolBar(shell, SWT.BORDER);
CoolItem item1 = new CoolItem(bar, SWT.NONE);
CoolItem item2 = new CoolItem(bar, SWT.NONE);
CoolItem item3 = new CoolItem(bar, SWT.NONE);
CoolItem item4 = new CoolItem(bar, SWT.NONE, 2);
可以通过锁定来禁止拖拽CoolItem。
bar.setWrapIndices(new int[] { 3 });
bar.setSize(300, 120);
Button button1 = new Button(bar, SWT.FLAT | SWT.BORDER);
button1.setText("Button");
button1.pack();
button1.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
bar.setLocked(!bar.getLocked());
}
});
Button button2 = new Button(bar, SWT.PUSH);
button2.setText("Another button");
button2.pack();
ToolBar tools = new ToolBar(bar, SWT.NONE);
ToolItem b1 = new ToolItem(tools, SWT.FLAT);
b1.setText("Tool");
ToolItem b2 = new ToolItem(tools, SWT.FLAT);
b2.setText("Bar");
tools.pack();
Point size = button1.getSize();
item1.setControl(button1);
item1.setSize(item1.computeSize(size.x, size.y));
size = button2.getSize();
item2.setControl(button2);
item2.setSize(item2.computeSize(size.x, size.y));
size = tools.getSize();
item3.setControl(tools);
item3.setSize(item3.computeSize(size.x, size.y));
item3.setMinimumSize(size);
通过创建简单的按钮,并为按钮添加监听器,来禁止和启用拖拽功能。然后创建了包含两个按钮的工具栏,并添加到CoolBar中。然后可以通过CoolItem的setControl方法来将CoolItem与空间联系起来,然后通过setSize方法来设置空间的初始值。通过设置setMinimumSize方法,用户可以调整CoolItem的大小。最后,通过调用setWrapIndices来将CoolItem隔开。使用setSize来指定在shell中的大小。
参考资料:
SWT主页:http://www.eclipse.org/swt
SWT小例子:http://www.eclipse.org/swt/snippets/
SWT例子:http://www.eclipse.org/swt/examples.php
SWT文档:http://www.eclipse.org/swt/docs.php
Getting Started with Eclipse 2.1 and the SWT: http://www.cs.umanitoba.ca/~eclipse/