RCP程序UI设计——之首页篇
来源:互联网 发布:淘宝客服和美工哪个好 编辑:程序博客网 时间:2024/05/17 05:08
在我们第一次启动eclipse时,首先呈现在我们眼前的是一个漂亮的欢迎界面,界面中提供了各种功能的快速入口,如帮助,示例程序和进入工作台等等操作,使用起来非常的直观和方便。
其实在我们开发的RCP程序中,一样也可以实现这样的效果,我们可以通过扩展"org.eclipse.ui.intro"这个扩展点来实现,下图是我在一个项目中所实现的界面。
下面就谈谈它的实现的过程。
实际上,在这个欢迎界面中也是使用的html脚本,而且也有css样式表,是通过org.eclipse.ui.intro. IintroPart来呈现出来的。也就是说,要实现这样的界面,第一步就是要先考虑如何解析并显示页面的内容,其次再来设计欢迎页面,更细节的就不再说了,一切以代码来说话。
下面是整个功能的实现过程:
1, 环境配置,本例使用了Eclipse3.3.1 + WTP插件来构建。
2, 先创建一个插件项目,项目名为intro.example,注意不是rcp项目。在plugin.xml页面中的Dependencies页面中的Required Plug-ins项目中加入“org.eclipse.ui.intro”,然后保存。
3, 再创建一个RCP项目,项目名为intro.example.rcp。在plugin.xml页面中的Dependencies页面中的Required Plug-ins项目中加入“intro.example”,然后保存。
4, 在项目intro.example中新建文件夹content,再在content下建子文件夹images,在images中放入处理好的图片,然后新建以下文件:
==========================================================
root.xhtml:
==========================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Welcome</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
<!--
function MM_preloadImages() { //v3.0
var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}
function MM_swapImgRestore() { //v3.0
var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_findObj(n, d) { //v4.01
var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
if(!x && d.getElementById) x=d.getElementById(n); return x;
}
function MM_swapImage() { //v3.0
var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
//-->
</script>
</head>
<body class="index" onload="MM_preloadImages('images/index_over_01.gif','images/index_over_07.gif','images/index_over_09.gif','images/index_over_14.gif','images/index_over_15.gif','images/index_over_19.gif','images/index_over_20.gif','images/index_over_22.gif','images/index_over_23.gif','images/index_over_26.gif','images/index_over_27.gif','images/index_over_28.gif','images/index_over_29.gif','images/index_over_30.gif')">
<div id="content">
<!-- This is where we use the Intro dynamicContent element. The class is loaded from the specified plugin. -->
<contentProvider id="contentProviderId" class="intro.example.IntroFeatureDynamicContent" pluginId="intro.example">
</contentProvider>
</div>
</body>
</html>
==========================================================
style.css:
==========================================================
html{
overflow:auto;
}
body.index {
background-color: #FFFFFF;
background-image: url(welcomebg.jpg);
background-repeat: no-repeat;
margin: 0px;
padding: 0px;
background-position: left top;
}
body.right {
background-color: #C8E8E8;
}
#content {
position:absolute;
left:226px;
top:127px;
width: 720px;
}
.right div {
font-family: "宋体";
font-size: 12px;
font-weight: bold;
color: #999999;
}
a:link {
color: #017781;
text-decoration: none;
}
a:visited {
color: #017781;
text-decoration: none;
}
a:hover {
color: #FF6600;
text-decoration: underline;
}
a:active {
color: #017781;
text-decoration: none;
}
再增加一个welcomebg.jpg文件作为背景。
5, 在项目intro.example中新建文件夹schema,新建featureLauncher.exsd扩展点描述文件,文件内容如下:
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="com.hailite.ui.intro">
<annotation>
<appInfo>
<meta.schema plugin="com.hailite.ui.intro" id="featureLauncher" name="featureLauncher"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<complexType>
<sequence>
<element ref="introLauncher"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="introLauncher">
<annotation>
<appInfo>
<meta.element labelAttribute="title" icon="image"/>
</appInfo>
</annotation>
<complexType>
<attribute name="title" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="perspectiveId" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="image" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="resource"/>
</appInfo>
</annotation>
</attribute>
<attribute name="disableImage" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="resource"/>
</appInfo>
</annotation>
</attribute>
<attribute name="overImage" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="resource"/>
</appInfo>
</annotation>
</attribute>
<attribute name="rule" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="shellActionId" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
</documentation>
</annotation>
</schema>
6, 在项目intro.example根目录下创建文件introContent.xml,内容如下: <?xml version="1.0" encoding="utf-8" ?> <introContent> <page id="root" content="content/root.xhtml"/> </introContent> 7, 在项目intro.example中增加两个类,如下: ========================================================== IntroFeatureDynamicContent.java ========================================================== package intro.example; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.intro.config.IIntroContentProviderSite; import org.eclipse.ui.intro.config.IIntroXHTMLContentProvider; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * 创建欢迎页面的内容 * @author 严军 * @create 2008-5-4 下午05:26:51 * @version v1.0 */ public class IntroFeatureDynamicContent implements IIntroXHTMLContentProvider { public static final String EXT_INTRO_LAUNCHER = "featureLauncher"; public void init(IIntroContentProviderSite site) { } public void createContent(String id, PrintWriter out) { } public void createContent(String id, Composite parent, FormToolkit toolkit) { } @SuppressWarnings("deprecation") public void createContent(String id, Element parent) { // 定义文档对象 Document dom = parent.getOwnerDocument(); // 得到所有扩展点的节点元素 IConfigurationElement[] providerElements = Platform .getExtensionRegistry().getConfigurationElementsFor( Activator.PLUGIN_ID, EXT_INTRO_LAUNCHER); int imageIndex = 0; for (IConfigurationElement providerElement : providerElements) { imageIndex++; // String title = providerElement.getAttribute("title"); // System.out.println("系统标题:" + title); String rule = providerElement.getAttribute("rule"); String perspectiveId = providerElement .getAttribute("perspectiveId"); // System.out.println("透视图ID:" + perspectiveId); String shellActionId = providerElement .getAttribute("shellActionId"); // System.out.println("外部程序:" + shellActionId); String imageFilename = providerElement.getAttribute("image"); // System.out.println("图片:" + imageFilename); String imageDisableFilename = providerElement .getAttribute("disableImage"); // System.out.println("Disable图片:" + imageDisableFilename); String imageOverFilename = providerElement .getAttribute("overImage"); // System.out.println("Over图片:" + imageOverFilename); // 创建图片 ImageDescriptor image = AbstractUIPlugin.imageDescriptorFromPlugin( providerElement.getDeclaringExtension() .getNamespaceIdentifier(), imageFilename); ImageDescriptor imageDisable = AbstractUIPlugin .imageDescriptorFromPlugin(providerElement .getDeclaringExtension().getNamespaceIdentifier(), imageFilename); // 得到当前元素的目录 Bundle bundle = Platform.getBundle(providerElement .getDeclaringExtension().getNamespaceIdentifier()); URL imageUrl = null; URL imageDisableUrl = null; URL imageOverUrl = null; if (imageFilename != null) imageUrl = bundle.getEntry(imageFilename); if (imageDisableFilename != null) imageDisableUrl = bundle.getEntry(imageDisableFilename); if (imageOverFilename != null) imageOverUrl = bundle.getEntry(imageOverFilename); try { if (imageUrl != null) { // 得到图片 imageUrl = FileLocator.resolve(imageUrl); // System.out.println("图片URL:" + imageUrl.toString()); } if (imageDisableUrl != null) { // 得到图片 imageDisableUrl = FileLocator.resolve(imageDisableUrl); // System.out.println("Disable图片URL:" // + imageDisableUrl.toString()); } if (imageOverUrl != null) { // 得到图片 imageOverUrl = FileLocator.resolve(imageOverUrl); // System.out.println("Over图片URL:" + // imageOverUrl.toString()); } } catch (IOException e) {} // 创建xhtml元素,这里是创建一个超链接 Element para = dom.createElement("span"); para.setAttribute("id", providerElement.getDeclaringExtension() .getNamespaceIdentifier() + "ContentId"); Element hrefPerspective = dom.createElement("a"); // 消除单击时出现的虚线框 hrefPerspective.setAttribute("onfocus", "this.blur();"); // Element hrefShell = dom.createElement("a"); String hrefParam = ""; if (perspectiveId == "" || perspectiveId == null) hrefParam = "launchShell?id=" + shellActionId; else hrefParam = "launchPerspective?id=" + perspectiveId; // 打开透视图的ID hrefPerspective.setAttribute("href", "http://org.eclipse.ui.intro/" + hrefParam); // 创建图片 Element img = dom.createElement("img"); String imageId = "Image" + imageIndex; img.setAttribute("id", imageId); img .setAttribute("src", imageUrl == null ? "" : imageUrl .toString()); img.setAttribute("width", String .valueOf(image.getImageData().width)); img.setAttribute("height", String .valueOf(image.getImageData().height)); img.setAttribute("style", "border: 0px;"); img.setAttribute("onmouseover", "MM_swapImage('" + imageId + "','','" + imageOverUrl + "',1)"); img.setAttribute("onmouseout", "MM_swapImgRestore()"); Element disable = dom.createElement("img"); disable.setAttribute("src", imageDisableUrl == null ? "" : imageDisableUrl.toString()); disable.setAttribute("width", String.valueOf(imageDisable .getImageData().width)); disable.setAttribute("height", String.valueOf(imageDisable .getImageData().height)); disable.setAttribute("style", "border: 0px;"); hrefPerspective.appendChild(img); // 添加文本节点 // href.appendChild(dom.createTextNode(" "+title)); if (((perspectiveId == null) || ("".equals(perspectiveId))) && ((shellActionId == null) || ("".equals(shellActionId)))) { para.appendChild(disable); } else { if (rule != null) { para.appendChild(disable); } else { para.appendChild(hrefPerspective); } } parent.appendChild(para); } } public void dispose() { } } ========================================================== LaunchPerspectiveAction.java ========================================================== package intro.example; import java.util.Properties; import org.eclipse.jface.action.Action; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.intro.IIntroSite; import org.eclipse.ui.intro.config.IIntroAction; import org.eclipse.ui.part.IntroPart; /** * 执行这个Action可以打开指定的透视图 * @author 严军 * @create 2008-5-4 下午05:28:14 * @version v1.0 */ public class LaunchPerspectiveAction extends Action implements IIntroAction { public void run(IIntroSite site, Properties params) { String perspectiveId = params.getProperty("id"); if (perspectiveId == null) return; try { IWorkbenchPage page = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage(); page.closeAllEditors(false); page.closeAllPerspectives(false, false); PlatformUI.getWorkbench().showPerspective(perspectiveId, PlatformUI.getWorkbench().getActiveWorkbenchWindow()); IntroPart part = (IntroPart) PlatformUI.getWorkbench() .getIntroManager().getIntro(); if (part != null) PlatformUI.getWorkbench().getIntroManager().closeIntro(part); } catch (Exception e) { // 忽略错误 } } }
8, 整个项目结构如下图:
9, 在项目intro.example的Extensions页面中增加扩展点三个扩展点,分别是"org.eclipse.ui.intro","org.eclipse.ui.intro.config"和"org.eclipse.ui.intro.configExtension"。整个plugin.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension-point id="featureLauncher" name="featureLauncher" schema="schema/featureLauncher.exsd"/>
<extension
point="org.eclipse.ui.intro">
<intro
class="org.eclipse.ui.intro.config.CustomizableIntroPart"
icon="icons/welcome16.gif"
id="intro.example.intro"
label="欢迎">
</intro>
</extension>
<extension
point="org.eclipse.ui.intro.config">
<config
content="introContent.xml"
id="intro.example.config"
introId="intro.example.config">
<presentation
home-page-id="root">
<implementation
kind="html"
os="win32,linux,macosx"
style="content/style.css">
</implementation>
</presentation>
</config>
</extension>
<extension
point="org.eclipse.ui.intro.configExtension">
<action
name="launchPerspective"
replaces="runAction?pluginId=intro.example&class=intro.example.LaunchPerspectiveAction">
</action>
</extension>
</plugin>
10, 重写项目intro.example.rcp中的ApplicationWorkbenchWindowAdvisor类的openIntro方法,目的是每次启动程序之后都能够打开欢迎界面,内容如下:
@Override
public void openIntro() {
IWorkbenchConfigurer wbConfig = getWindowConfigurer()
.getWorkbenchConfigurer();
final String key = "introOpened"; //$NON-NLS-1$
Boolean introOpened = (Boolean) wbConfig.getData(key);
if (introOpened != null && introOpened.booleanValue()) {
return;
}
wbConfig.setData(key, Boolean.TRUE);
boolean showIntro = PrefUtil.getAPIPreferenceStore().getBoolean(
IWorkbenchPreferenceConstants.SHOW_INTRO);
if (!showIntro) {
return;
}
if (wbConfig.getWorkbench().getIntroManager().hasIntro()) {
wbConfig.getWorkbench().getIntroManager().showIntro(
getWindowConfigurer().getWindow(), false);
// 设置下次启动程序时时否打开欢迎页面
PrefUtil.getAPIPreferenceStore().setValue(
IWorkbenchPreferenceConstants.SHOW_INTRO, true);
PrefUtil.saveAPIPrefs();
}
}
打开项目intro.example.rcp中的plugin.xml文件,Extensions页面中增加扩展点"intro.example.featureLauncher">,然后再在introLauncher属性中输入相应的值。最后把intro.example和intro.example.rcp这两个项目进行绑定,再增加扩展点"org.eclipse.ui.intro",加入“introProductBinding”这个属性,如下图所示:
整个plugin.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
id="application"
point="org.eclipse.core.runtime.applications">
<application>
<run
class="intro.example.rcp.Application">
</run>
</application>
</extension>
<extension
point="org.eclipse.ui.perspectives">
<perspective
name="RCP Perspective"
class="intro.example.rcp.Perspective"
id="intro.example.rcp.perspective">
</perspective>
</extension>
<extension
id="product"
point="org.eclipse.core.runtime.products">
<product
application="intro.example.rcp.application"
name="Hello RCP">
<property
name="windowImages"
value="icons/alt_window_16.gif,icons/alt_window_32.gif">
</property>
<property
name="appName"
value="Hello RCP">
</property>
</product>
</extension>
<extension
point="intro.example.featureLauncher">
<introLauncher
disableImage="icons/images/index_disable_01.gif"
image="icons/images/index_01.gif"
overImage="icons/images/index_over_01.gif"
perspectiveId="intro.example.rcp.perspective"
title="任务1"></introLauncher>
</extension>
<extension
point="org.eclipse.ui.intro">
<introProductBinding
introId="intro.example.intro"
productId="intro.example.rcp.product">
</introProductBinding>
</extension>
</plugin>
11, 运行项目intro.example.rcp,效果如下图:
- RCP程序UI设计——之首页篇
- 程序UI设计——工业软件UI 设计心得
- BootStrap之——网站首页整体设计思路
- “优觅网”网站设计—首页
- UI设计 - 首页(主页)的任务
- Eclipse RCP之视图—view
- Eclipse RCP之视图—view
- Eclipse Rcp学习系列02—— 第一个Rcp程序
- 微信小程序之UI篇
- 微信小程序之商城首页
- 产品经理之UI设计——UI/UX设计趋势
- UI——Material Design设计之Toolbar详解
- UI——Material Design设计之滑动菜单详解
- unity之UI设计—简单按钮界面
- 【SSH网上商城项目实战14】商城首页UI的设计
- 【SSH网上商城项目实战14】商城首页UI的设计
- 【SSH网上商城项目实战14】商城首页UI的设计
- RCP应用程序开发之二——核心类总结
- 基于 OSGi 和 Spring 开发 Web 应用
- HelloWorld问题集精华
- powerdesigner 反向工程时出错,unable to list users
- 学了三天TCL,写了个小程序,到此为止
- 程序员的十层楼
- RCP程序UI设计——之首页篇
- JAVA中SWing的作用?
- 修改MFC模板写的程序的EXE文件的图标
- 国际IT大佬访华忙
- linux下的TCP/IP socket 文件传输
- 一些轻量级的数据库:SQLite Perst Firebird
- Linux 下Socket编程基础
- ASP对象server的实践
- 批量提取网页数据