Eclipse RCP中嵌套组件

Swing与SWT是基于Java的两种完全不同的视图控件技术,前者是jdk自带,后者是Eclipse的衍生物,两者都有广大的用户群,而结合使用的案例也很多,笔者使用Swing多年,最近有幸作了个Eclipse RCP与Swing结合的例子,期间发现了些难点,特作本文了以皮毛之见。

相关概念

Swing
Swing为JDK自带,是正统的java界面控件,历史悠久,设计优雅,是java开发界面组件的第一选择,但Swing组件更新缓慢,几年来都没有太大变化,加上官方NetBeans臃肿缓慢的表现,让依赖本地库、界面native的SWT得以发展壮大。

SWT
SWT是eclipse项目的衍生物,全称是“Standard Widget Toolkit”,SWT需要依赖本地库,界面风格与本地程序协调一致,借助eclipse的优秀表现,SWT给人以运行流畅,界面漂亮的印象,赢得了不少用户的青睐。

Eclipse RCP
Eclipse RCP是一个用于创建和部署富客户端应用的平台,它包含Equinox(一个基于OSGi标准的组件框架),用于构建丰富的具有本地GUI的桌面应用程序,并提供通过服务端升级桌面程序的完整体系。

如何创建Eclipse RCP项目

安装插件
首先我们需要安装Eclipse RCP Plug-in Developer Resources插件,当然你也可以使用Eclipse IDE for Java EE Developer,这个版本的Eclipse包含的插件比较全

创建一个Plug-in Project,添加两个View到透视图
新建一个Plug-in Project,向导中,Rich Client Application选项选择yes,后面有模版可供选择,不熟悉Eclipse RCP的可以选个模版练手。
Eclipse RCP中每个ViewPart表示一个可插拔的视图,而Perspective类的作用是对View作布局,这里我们创建两个view:NavigationView,View,左边导航树(借用了RCP自带的mail模版),右边主面板用来嵌入Swing组件,初步为如下效果:

如何在Eclipse RCP中嵌入Swing组件

Eclipse RCP详细使用说明可以参考文档:http://www.vogella.de/articles/EclipseRCP/article.html,本文的主要目的是介绍Swing组件的嵌入,下面我们在右边的View中加入一个Swing面板。

使用SWT_AWT桥实现Swing组件的嵌入,使用SWT_AWT.new_Frame(composite)实现SWT组件中嵌入AWT的Frame对象,而AWT的Frame中就可以添加Swing组件了,参考下面的代码

public class View extends ViewPart {
	public static final String ID = "HelloRCP.view";
	private JPanel swingPanel;

	public void createPartControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
		final Frame frame = SWT_AWT.new_Frame(composite);
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				swingPanel = new JPanel();
				JButton button = new JButton("Swing Button");
				swingPanel.add(button);
				frame.add(swingPanel);
			}
		});
	}
	public void setFocus() {}
}

运行效果:

Eclipse UI线程与Swing事件派发线程

上面的代码中我们留意到,创建Swing的JPanel我们是在Swing的事件派发线程(EDT)中调用的,EDT的作用是保证Swing线程的安全,任何Swing界面相关的操作都需要在EDT中执行,与Swing的这一设计类似,SWT也有一个UI线程,任何SWT界面相关的操作都必需在这个UI线程中调用,下面我们对按钮添加点击监听,实现视图名称的修改,注意代码需要在getDisplay().asyncExec中调用

public void createPartControl(Composite parent) {
	Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
	final Frame frame = SWT_AWT.new_Frame(composite);
	SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			swingPanel = new JPanel();
			swingPanel.setDoubleBuffered(true);
			JButton button = new JButton("Click and change view name");
			button.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					getSite().getShell().getDisplay().asyncExec(new Runnable() {
						public void run() {
							View.this.setPartName("New Swing View");
						}
					});
				}
			});
			swingPanel.add(button);
			frame.add(swingPanel);
		}
	});
}

嵌入TWaver Demo

嵌入了Swing组件,可惜不够好看,直接把TWaver Demo放进来如何,于是拷贝TWaver Demo的源码,引用twaver.jar到build path,在createPartControl(Composite parent)中创建一个demo.MainPane,放到右边的面板中:

public void createPartControl(Composite parent) {
	Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
	final Frame frame = SWT_AWT.new_Frame(composite);
	SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			Demo.init();
			MainPane mainPanel = new MainPane();
			mainPanel.setDoubleBuffered(true);
			frame.add(mainPanel);
			...
	});
}

Eclipse RCP工程中如何引入第三方jar

这里还有件重要的事要做,Eclipse RCP中使用第三方jar需要在Runtime Classpath中引入这个jar,可以按下图中的设置

Eclipse View之间如何交互

Eclipse RCP框架中,每个view都是独立的,在一个view中没法直接得到另一个view的实例,要实现view之间的交互需要一些特殊手段,如通过selection监听器监听其他视图的selection事件,详细使用可参考http://www.cnblogs.com/zephyr/archive/2008/05/30/1210477.html

本例中实现的是点击左边SWT的导航树,同步选中右边TWaver的对应的树节点,要实现这样的功能,要求右边的视图能监听左边视图的变化事件,首先我们在NavigationView中注册导航树为事件提供者:
注意下面的这行代码:this.getSite().setSelectionProvider(treeViewer);其作用是向系统提供一个消息源,这样当这个树选中变化时,别的视图就可以监听到这些事件

public void createPartControl(Composite parent) {
		treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		...
		this.getSite().setSelectionProvider(treeViewer);
		...
	}

然后在View视图中监听上面的消息源

public void createPartControl(Composite parent) {
	...
	this.getSite().getPage().addSelectionListener(NavigationView.ID, new ISelectionListener() {
		public void selectionChanged(IWorkbenchPart arg0, ISelection arg1) {
			...
		}
	});
	...
}

通过以上两步就实现了视图View监听视图NavigationView中变化事件的功能,同理,如果需要在NavigationView视图中监听View视图中的事件,则需要注册View为事件源,然后在NavigationView中监听该事件,有了这种消息传递机制,我们就可以实现各个视图间的通信了,而具体同步的代码我这里就不多说了。

补充一个小技术点

Windows操作系统下,SWT中的Swing组件可能出现闪烁的问题,可以通过调用下面的函数,设置为true,以避免该问题

JComponent#public void setDoubleBuffered(boolean aFlag)

最终运行结果

转载于:https://my.oschina.net/monolog/blog/404843

开发项目用SWING与RCP与SWT.JFACE的分析 第一个SWT程序 下面让我们开始一个SWT程序。(注意:以下的例子和说明主要针对Windows平台,其它的操作系统应该大同小异)。首先要在Eclipse安装文件找到SWT包,Eclipse组织并不提供单独的SWT包下载,必须下载完整的Eclipse开发环境才能得到SWT包。SWT是作为Eclipse开发环境的一个插件形式存在,可以在${你的eclipse安装路径}\plugins路径下的众多子目录下去搜索SWT.JAR文件,在找到的JAR文件包含了SWT全部的Java类文件。因为SWT应用了JNI技术,因此同时也要找到相对应的JNI本地化库文件,由于版本和操作平台的不同,本地化库文件的名称会有些差别,比如SWT-WIN32-2116.DLL是Window平台下Eclipse Build 2116的动态库,而在Unix平台相应版本的库文件的扩展名应该是.so,等等。注意的是,Eclipse是一个开放源代码的项目,因此你也可以在这些目录找到SWT的源代码,相信这会对开发很有帮助。下面是一段打开空窗口的代码(只有main方法)。 import com.e2one.example; public class OpenShell{ public static void main(String [] args) { Display display = new Display(); Shell shell = new Shell(display); shell.open(); // 开始事件处理循环,直到用户关闭窗口 while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } } 确信在CLASSPATH包括了SWT.JAR文件,先用Javac编译例子程序。编译无错后可运行java -Djava.library.path=${你的SWT本地库文件所在路径} com.e2one.example.OpenShell,比如SWT-WIN32-2116.DLL件所在的路径是C:\swtlib,运行的命令应该是java -Djava.library.path=c:\swtlib com.e2one.example.OpenShell。成功运行后,系统会打开了一个空的窗口。 剖析SWT API 下面再让我们进一步分析SWT API的组成。所有的SWT类都用org.eclipse.swt做为包的前缀,下面为了简化说明,我们用*号代表前缀org.eclipse.swt,比如*.widgets包,代表的是org.eclipse.swt.widgets包。 我们最常用的图形构件基本都被包括在*.widgets包,比如Button,Combo,Text,Label,Sash,Table等等。其两个最重要的构件当数Shell和Composite。Shell相当于应用程序的主窗口框架,上面的例子代码就是应用Shell构件打开一个空窗口。Composite相当于SWING的Panel对象,充当着构件容器的角色,当我们想在一个窗口加入一些构件时,最好到使用Composite作为其它构件的容器,然后再去*.layout包找出一种合适的布局方式。SWT对构件的布局也采用了SWING或AWTLayout和Layout Data结合的方式,在*.layout包可以找到四种Layout和与它们相对应的布局结构对象(Layout Data)。在*.custom包,包含了对一些基本图形构件的扩展,比如其的CLabel,就是对标准Label构件的扩展,上面可以同时加入文字和图片,也可以加边框。StyledText是Text构件的扩展,它提供了丰富的文本功能,比如对某段文字的背景色、前景色或字体的设置。在*.custom包也可找到一个新的StackLayout布局方式。 SWT对用户操作的响应,比如鼠标或键盘事件,也是采用了AWT和SWING的Observer模式,在*.event包可以找到事件监听的Listener接口和相应的事件对象,例如常用的鼠标事件监听接口MouseListener,MouseMoveListener和MouseTrackListener,及对应的事件对象MouseEvent。 *.graphics包可以找到针对图片、光标、字体或绘图的API。比如可通过Image类调用系统不同类型的图片文件。通过GC类实现对图片、构件或显示器的绘图功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值