IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Open source  >

探索 Eclipse 的嵌入式富客户端平台

移动设备需要 Eclipse

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

样例代码


级别: 初级

Chris Aniszczyk (zx@us.ibm.com), 软件工程师, IBM
Uriel Liu (liukl@tw.ibm.com), 软件工程师, IBM

2006 年 3 月 21 日

本文介绍了嵌入式富客户端平台(embedded Rich Client Platform,eRCP)。将学习构成 eRCP 的各种组件,并得到在应用程序中使用它们的一些示例。

背景

嵌入式富客户端平台(eRCP)的目的是把 Eclipse 的富客户端平台(RCP)带到嵌入式领域。

eRCP 由以下组件构成:

  • 标准部件工具包(eSWT)—— 核心,扩展和移动扩展
  • eJFace
  • eWorkbench
  • eUpdate

我们将讨论每个组件,并在合适的地方使用代码示例。





回页首


eSWT

嵌入式标准部件工具包(eSWT)是著名的 Java™ 图形工具包 —— 标准部件工具包(SWT)—— 的子集。它提供了一套控件、面板和其他常用的部件,作为用户界面的构造块。除了 SWT 中原来包含的部件之外,eSWT 还引入了一个新组件:移动扩展(由 IBM、Nokia 和 Motorola 联合设计的规范),主要针对的是像 PDA 和智能手机这样的移动设备。

从平台独立性的角度来说,eSWT 的设计与它的近亲 SWT 不同。SWT 使用平台独立的方式,试图保持本机代码尽可能简单,以便提高在不同操作系统之间的可移植性。问题在于:可移植性和性能是一对矛盾的问题,所以 eSWT 决定采用另一种方式:通用图形层(UGL),它仍然把 Java 的本机界面(JNI)保留在本机工具包实现上。但是,UGL 没有充当一对一的 JNI 包装器,而试图保持本机实现尽可能接近,只需要通过 JNI 进行回调的信息。eSWT 的方式牺牲了可移植性,因为本机工具包完全依赖于它使用的图形系统,但是这种方式极大地提高了性能(移动设备上的主要考虑因素)。

eSWT 中包含了三个组件(请参阅图 1 ):

  • 核心
  • 扩展的
  • 移动扩展

图 1. eSWT 用户界面工具包
eSWT 用户界面工具包

核心和扩展组件是 eSWT 的子集。新发明的移动扩展组件针对的是移动设备。这种组件构成方式支持根据设备的能力和目的,灵活地对设备上要包含哪些组件进行配置。核心组件是必需的,包含运行基本应用程序所必需的最小功能。扩展和移动扩展组件是可选的。

在后面的小节中,我们将研究每个组件,同时提供示例应用程序。

eSWT 核心

eSWT 核心包含基本的用户界面元素,包括低级图形、事件和基本的部件基础设施。表 1 显示了 eSWT 核心中的类。

表 1. eSWT 核心 org.eclipse 类
swt.widgetsswt.graphicsswt.eventsswt.layoutswt.swt
ButtonColorControlEventFormLayoutSWT
CanvasDeviceDisposeEventFormDataSWTException
ComboFontFocusEventFormAttachmentSWTError
CompositeFontDataKeyEvent--
ControlFontMetricsMenuEvent--
DecorationsGCModifyEvent--
DialogImageMouseEvent--
DisplayImageDataPaintEvent--
EventPaletteDataSelectionEvent--
FileDialogPointShellEvent--
ItemRectangleTraverseEvent--
LabelResourceTypedEvent--
LayoutRGBVerifyEvent--
List----
Menu/MenuItem----
MessageBox----
ProgressBar----
Scrollable----
Scrollbar----
Shell----
Slider----
Synchronizer----
Text----
TypedListener----

eSWT 核心的示例

我们从一个完整的 eSWT 程序开始,这个程序创建一个窗口,在应用程序的标题栏上显示 “HelloWorld”。然后我们将添加一些核心控件(文本、按钮、列表)。对于布局,我们采用 FormLayoutFormData。还将在按钮上添加 SelectionListener,它将弹出一个消息框。完整的代码如清单 1 所示。


清单 1:eSWAT 风格的 HelloWorld

01 public class HelloWorldeSWT {
02 
03   public static void main(String[] args) {
04     Display display = new Display();
05     final Shell shell = new Shell(display);
06 		
07     Text text = new Text(shell,SWT.SINGLE);
08     text.setText("This is a text");		
09     Button buttonleft = new Button(shell, SWT.PUSH);
10     buttonleft.setText("Left Push!");
11     Button buttonright = new Button(shell, SWT.PUSH);
12     buttonright.setText("Right Push!");
13     buttonright.addSelectionListener(new SelectionListener(){
14       public void widgetSelected(SelectionEvent e) {
15         MessageBox messageBox = new MessageBox(shell,
16           SWT.ICON_INFORMATION| SWT.YES | SWT.NO);
17         messageBox.setText("MessageBox");
18         messageBox.setMessage("Can you see me?");
19         messageBox.open();
20       }
21       public void widgetDefaultSelected(SelectionEvent e) {
22       }});
23     List list = new List(shell,SWT.MULTI|SWT.BORDER);
24     for (int i=0; i<5; i++) {
25 list.add("item "+i);
26     }
27     
28     shell.setText("HelloWorld from eSWT");
29     FormLayout layout = new FormLayout();
30     layout.spacing = 5;
31     layout.marginHeight = layout.marginWidth = 9;
32     shell.setLayout(layout);
33     
34     FormData textData = new FormData();
35     textData.top = new FormAttachment(0);
36     textData.left = new FormAttachment(0);
37     textData.right = new FormAttachment(90);
38     text.setLayoutData(textData);
39     
40     FormData buttonleftData = new FormData();
41     buttonleftData.top = new FormAttachment(text);
42     buttonleftData.left = new FormAttachment(0);
43     buttonleftData.right = new FormAttachment(40);
44     buttonleft.setLayoutData(buttonleftData);
45     
46     FormData buttonrightData = new FormData();
47     buttonrightData.top = new FormAttachment(text);
48     buttonrightData.left = new FormAttachment(buttonleft);
49     buttonright.setLayoutData(buttonrightData);
50     FormData listData = new FormData();
51     
52     listData.top = new FormAttachment(buttonleft);
53     list.setLayoutData(listData);
54     
55     shell.setSize(240,320);
56     shell.open();
57     
58     while (!shell.isDisposed()) {
59 if (!display.readAndDispatch())
60 	display.sleep();
61     }
62     display.dispose();
63   }

图 2 显示了在日文版 PocketPC 设备上运行的应用程序。当用户按下 Right Push! 按钮时,就出现一个消息框(如图 3 所示)。eSWT 利用底层的本机图形支持来提供一致的用户界面(本机应用程序的观感,而不是发明一个新外观)。


图 2. eSWT 风格的 HelloWorld
eSWT 风格的 HelloWorld

图 3. 具有本机观感的消息框
具有本机观感的消息框

示例评价

对于清单 1 中的代码实现的效果,值得逐行进行解释。

行 04-05:
创建了显示和外壳。外壳把显示设置成自己的双亲,并把它变成顶级窗口。在 PocketPC 平台上,顶级窗口 全都自动最大化,保持一致性。我们用 final 限定符创建外壳,因为稍后要在 SelectionListener 中使用它。
行 07-08:
创建文本并调用 setText() 来设置文本字符串。
行 09-22:
创建了两个按钮。在右侧的按钮上,添加了 SelectionListener,以弹出一个简单的消息框。
行 23-26:
创建了一个包含五个项目的列表。
行 28:
设置窗口标题栏上的文本。
行 29-53:
FormLayoutFormDataFormAttachment 协助布局过程。
行 55-56:
设置外壳尺寸并打开外壳。在这个示例中,setSize() 对顶级窗口不生效(因为设备的原因)。
行 58-61:
while() 循环内部建立了一个显式循环,不断地读取和分派来自操作系统的用户事件。如果再没有事件发生,就调用 display.sleep() 并进入睡眠,等待下一个事件。
行 62:
代码最后一行的 display.dispose() 调用显式地清除显示,并释放 eSWT 应用程序的所有相关资源。

eSWT 扩展

eSWT 扩展是可选组件,包含多个复杂的用户界面元素和布局。这些功能通常在高端移动设备和 PDA 中才能找到。表 2 显示了 eSWT 扩展中的类的详细列表。

表 2. eSWT 扩展的类
org.eclipse.swt.widgetsorg.eclipse.swt.browserorg.eclipse.swt.dndorg.eclipse.swt.graphics
ColorDialogBrowserByteArrayTransferImageLoader
DirectoryDialogLocationEventClipboard-
FontDialogProgressEventTextTransfer-
TableStatusTextEventTransfer-
TreeTitleEventTransferData-

eSWT 扩展的示例

Browser 部件是 eSWT 扩展中一个有意思的部件。我们将用 Broswer 控件创建一个完全能够工作的 Web 浏览器(请参阅清单 2)。在这个示例中将允许用户设置 URL、前进、后退或重新装入页面。


清单 2. 简单的 HTML 浏览器

public class BrowserTest {
	
	static Button prev, reload, next, go;
	static Text url;
	static Browser browser;
	
	
	public static void main(String[] args) {
		final Display display = new Display();
		Shell shell = new Shell(display);
		
		//set window title and size
		shell.setText("SimpleBrowser");
		shell.setSize(240,320);
		
		//previous button
		prev = new Button(shell, SWT.PUSH);
		prev.setText("<<");
		prev.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.back();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//reload button
		reload = new Button(shell, SWT.PUSH);
		reload.setText("R");
		reload.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.refresh();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//next button
		next = new Button(shell, SWT.PUSH);
		next.setText(">>");;
		next.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.forward();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// url text
		url = new Text(shell, SWT.SINGLE|SWT.BORDER);
		url.setText("http://");
		
		// go button
		go = new Button(shell, SWT.PUSH);
		go.setText("GO");
		go.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				browser.setUrl(url.getText());
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// browser
		browser = new Browser(shell, SWT.NONE);
		browser.setUrl("http://www.google.com");
		
		FormLayout formLayout = new FormLayout();
		shell.setLayout(formLayout);
		formLayout.spacing = 1;
		formLayout.marginHeight = formLayout.marginWidth = 2;
		
		FormData prevData = new FormData();
		prevData.left = new FormAttachment(0);
		prevData.top = new FormAttachment(0);
		prevData.width = 16;
		prev.setLayoutData(prevData);
		
		FormData reloadData = new FormData();
		reloadData.left = new FormAttachment(prev);
		reloadData.top = new FormAttachment(0);
		reloadData.width = 16;
		reload.setLayoutData(reloadData);
		
		FormData nextData = new FormData();
		nextData.left = new FormAttachment(reload);
		nextData.top = new FormAttachment(0);
		nextData.width = 16;
		next.setLayoutData(nextData);
		
		FormData urlData = new FormData();
		urlData.left =  new FormAttachment(next);
		urlData.top = new FormAttachment(0);
		urlData.right = new FormAttachment(89);
		urlData.bottom = new FormAttachment(browser);
		url.setLayoutData(urlData);
		
		FormData goData = new FormData();
		goData.left = new FormAttachment(url);
		goData.top = new FormAttachment(0);
		goData.width = 24;
		go.setLayoutData(goData);
		
		FormData browserData = new FormData();
		browserData.top = new FormAttachment(prev);
		browserData.left = new FormAttachment(0);
		browserData.right = new FormAttachment(100);
		browserData.bottom = new FormAttachment(100);
		browser.setLayoutData(browserData);
		
		shell.open();
		while( !shell.isDisposed() ) {
			if( !display.readAndDispatch() )
				display.sleep();
		}
		display.dispose();	
	}
}

图 4 显示了在 PocktPC 上运行的简单浏览器。


图 4. 简单的浏览器
简单的浏览器

eSWT 移动扩展

eSWT 移动扩展是可选组件,提供了在无数移动设备上常见的用户界面元素。表 3 显示了 eSWT 移动扩展组件中的类。

表 3. eSWT 移动扩展类
org.eclipse.ercp.swt.mobile
CaptionedControl
Command
ConstrainedText
DateEditor
HyperLink
Input
ListBox/ListBoxItem
MobileDevice/MovileDeviceEvent/MobileDeviceListener
MobileShell
MultiPageDialog
QueryDialog
Screen/ScreenEvent/ScreenListener
SortedList
TaskTip
TextExtension
TimedMessageBox

eSWT 移动扩展示例

在这个示例中,将采用 MobileShell 代替 Shell 来提供全屏幕功能。MobileShell 在顶部包含一个 SortedList,在底部包含一个 ListView。命令与 MobileShell 关联起来,让用户可以改变全屏幕模式,并用 ListView 改变布局的密度。源代码如清单 3 所示。


清单 3. MobileExtension 示例

public class MobileExtensionSample implements IPlatformRunnable {
	public static void main(String[] args) {
		Display display = new Display();
		final MobileShell shell = new MobileShell(display);
		final Button resetButton = new Button(shell, SWT.PUSH|SWT.BORDER);
		
		Command shellCommand = new Command(shell, Command.SELECT,0);
		shellCommand.setText("FullScreen");
		shellCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				shell.setFullScreenMode(true);
				resetButton.setVisible(true);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		resetButton.setText("Normal Screen");
		resetButton.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				shell.setFullScreenMode(false);
				resetButton.setVisible(false);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// Create SortedList and add items
		SortedList sortedList = new SortedList(
				shell, 
				SWT.MULTI|SWT.V_SCROLL|SWT.BORDER, 
				SortedList.FILTER);
		sortedList.add("banana");
		sortedList.add("123");
		sortedList.add("12");
		sortedList.add("happyhour");
		sortedList.add("toobad");
		sortedList.add("youknowwhat");
		sortedList.add("yes");
		sortedList.add("886222333");
		
		// Create ListView and add items with image set
		Image[] image = new Image[4];
		image[0] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[1] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[2] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[3] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		
		final ListView lv = new ListView(shell, SWT.MULTI|SWT.BORDER);
		for (int i=0; i<20; i++) {
			lv.add("item"+i, image[i % 4]);
		}
		
		//Create a Command for setting low density
		Command lowCommand = new Command(lv, Command.SELECT, 0);
		lowCommand.setText("LOW");
		lowCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				lv.setLayoutDensity(ListView.LOW);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//Create a Command for setting high density
		Command midCommand = new Command(lv, Command.SELECT, 0);
		midCommand.setText("MEDIUM");
		midCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				lv.setLayoutDensity(ListView.MEDIUM);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		FormLayout layout = new FormLayout();
		layout.spacing = 2;
		layout.marginHeight = layout.marginHeight = 2;
		shell.setLayout(layout);
		FormData sortedListData = new FormData();
		sortedListData.top = new FormAttachment(0);
		sortedListData.left = new FormAttachment(0);
		sortedListData.right = new FormAttachment(100);
		sortedListData.height = 120;
		sortedList.setLayoutData(sortedListData);
		FormData lvData = new FormData();
		lvData.top = new FormAttachment(sortedList);
		lvData.right = new FormAttachment(100);
		lvData.left = new FormAttachment(0);
		lvData.height = 130;
		lv.setLayoutData(lvData);
		FormData resetData = new FormData();
		resetData.top = new FormAttachment(lv);
		resetData.left = new FormAttachment(0);
		resetButton.setLayoutData(resetData);
		resetButton.setVisible(false);
		
		shell.setSize(240,320);
		shell.setText("Mobile Example");
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

图 5 显示了在 PocketPC 平台上运行的结果,图 6 显示了全屏幕模式。


图 5. 带有 SortedList 和 ListView 的 MobileShell
带有 SortedList 和 ListView 的 MobileShell

图 6. 全屏幕 MobileShell
全屏幕 MobileShell




回页首


eJFace

eJFace 是一个依赖 eSWT 的平台独立的用户界面工具包。eJFace 提供了一套组件和辅助工具,可以简化基于 eSWT 的应用程序的开发(通过对 eSWT 部件进行包装),就像 JFace 帮 SWT 做的事一样。实际上,eJFace 是 JFace 的一个严格的子集,所以它与它的近亲有许多相似性。eJFace 提供了对资源管理、查看器、动作和首选项页面的支持。在 参考资料 中有介绍 JFace 的教程,可以帮助您使用 eJFace。

eJFace 中可用的查看器类型有:

  • CheckBoxTableViewer
  • CheckBoxTreeViewer
  • ComboViewer
  • ListViewer
  • TableViewer
  • TreeViewer




回页首


eWorkbench

eWorkbench 允许 eRCP 应用程序在一个工作台窗口中同时运行,类似在 RCP 中的工作情况。eWorkbench 客户机提供了特定显示场景的视图,而且 eWorkbench 会自动根据使用的移动设备决定使用哪个视图。在 eWorkbench 中,没有透视图(perspective)的概念 —— 可以把它当成只有一个共享透视图的应用程序 —— 原因是这个概念在嵌入式设备上不适用。

eWorkbench 应用程序开发

创建 eWorkbench 应用程序只需要几步(RCP 开发人员会很熟悉)。过程与使用 contribution 的概念创建 Eclipse RCP 应用程序的过程类似。

步骤 1:定义视图

eWorkbench 允许定义三类视图,这三类视图都扩展自 org.eclipse.ui.part.ViewPart。正常视图是必需的,其他两个视图是可选的。

  • 正常(Normal): 默认视图
  • 大(Large): 显示器比较大的时候使用这个视图。
  • 状态(Status): 显示器比较小的时候使用这个视图

现在创建一个示例视图。


清单 4. 示例视图

public class DefaultView extends ViewPart {
	public void createPartControl(Composite parent) { 
	//create a composite with fill layout to host a label
	Composite composite = new Composite(parent, SWT.NONE);
	composite.setLayout(new FillLayout());
	// create a label 
	Label label = new Label(composite,SWT.CENTER); 
	label.setText("Hello eWorkbench!"); }
	public void setFocus() {}
}

通过使用扩展点机制,让 Eclipse 知道有可用的视图(请参阅清单 5)。


清单 5. plugin.xml

<extension point="org.eclipse.ui.views"> 
	<view allowMultiple="false"
		category="org.eclipse.ercp.eworkbench.viewCategory" 
		class="com.ibm.ercp.application.views.DefaultView" 
		icon="icons/sample.gif"
		id="com.ibm.ercp.application.defaultView" 
		name="Sample DefaultView"/> 
</extension>

步骤 2:定义 eWorkbench contribution

要成为 eWorkbench 应用程序,必须扩展 org.eclipse.ercp.eworkbench.applications 扩展点,并提供一些信息(请参阅清单 6 中的示例):

  • id: 代表 eWorkbench 应用程序的惟一标识符
  • name: 应用程序的名称(在工作台上显示)
  • views: 应用程序支持的视图(正常、大、状态)

清单 6. plugin.xml

<extension point="org.eclipse.ercp.eworkbench.applications">
	<application id="com.ibm.ercp.application" name=\
	"IBM Sample Application" singleton="true"> 
		<views normal="com.ibm.ercp.application.views.normal" />
	</application> 
</extension>

图 7 显示了 eWorkbench 应用程序列表的一个挨一个的截屏,后面是刚启动的示例应用程序。


图 7. Hello, eWorkbench
Hello, eWorkbench




回页首


eUpdate

RCP 提供的一个优势是用更新管理器界面从中央服务器更新插件的能力。也有与更新管理器关联的特性,例如调度更新。而且,通过使用开放网格服务基础设施(OGSI)和插件,可以动态地安装特性。eRCP 对这些优势的回答是 eUpdate,在编写这篇文章的时候它正在开发当中。

eUpdate 为需要包含更新管理功能的插件提供逻辑和用户界面。可以在这些插件的帮助下,或者通过使用 eUpdate 工作台应用程序提供对更新相关信息进行配置的完整 GUI,编写自己的更新功能。





回页首


结束语

这篇文章介绍了嵌入式富客户端平台(eRCP)和它的各种组件,提供了示例代码,包括示例 eWorkbench 应用程序和其他可以作为独立示例的代码清单。






回页首


下载

描述名字大小下载方法
Sample codeos-ecl-rcp-com.ibm.ercp.application_1.0.0.jar25KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论


作者简介

Chris Aniszczyk 是 IBM Lotus 的软件工程师和 IBM 的 Extreme Blue 实习项目的毕业生。他是衷心的开放源码支持者,一直在 Gentoo Linux (http://www.gentoo.org)发布方面工作,是 Eclipse Modeling Framework Technology(EMFT)项目的参与者。


Uriel Liu 是 IBM 中国软件开发实验室的软件开发人员,一直从事 WED 客户技术。他也是 eRCP 项目的参与者。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款