from:http://blog.csdn.net/liaojiyong/archive/2007/10/31/1858743.aspx
每当做开发的时候,你有可能在一次调试程序的过程中打开很多个编辑器,或是对Eclipse默认的视图布局不满意,手工作了一些调整。如果在工作的过程你因为有事离开或是不小心把Eclipse关掉了,不用担心,在你下次打开的时候,Eclipse仍然会为您记住上次的工作场景。下面是一个例子场景:
Eclipse会记住“包资源管理器”的当前展开元素、被选中元素、视图大小、位置、过滤、排序等状态。不止于视图和编辑器,Eclipse还提供了对全局状态的持久化机制。包括向导,Action等
GUI状态持久化不是必须的,只是一种可选的增强功能。一个完整的复杂的产品,特别是针对IDE类型的RCP,这个特征就显得比较人性化。
下面介绍一些个人的实践心得,愿大家有所收获,主要是针对视图(IViewPart)。
一般视图都是继承自ViewPart类或是实现IViewPart接口,在ViewPart中可以发现有
Java代码
/** *//**
* Initializes this view with the given view site. A memento is passed to
* the view which contains a snapshot of the views state from a previous
* session. Where possible, the view should try to recreate that state
* within the part controls.
* <p>
* This method is automatically called by the workbench shortly after the part
* is instantiated. It marks the start of the views's lifecycle. Clients must
* not call this method.
* </p>
*
* @param site the view site
* @param memento the IViewPart state or null if there is no previous saved state
* @exception PartInitException if this view was not initialized successfully
*/
public void init(IViewSite site, IMemento memento) throws PartInitException;
/** *//**
* Saves the object state within a memento.
*
* @param memento a memento to receive the object state
*/
public void saveState(IMemento memento);
/** *//**
* Initializes this view with the given view site. A memento is passed to
* the view which contains a snapshot of the views state from a previous
* session. Where possible, the view should try to recreate that state
* within the part controls.
* <p>
* This method is automatically called by the workbench shortly after the part
* is instantiated. It marks the start of the views's lifecycle. Clients must
* not call this method.
* </p>
*
* @param site the view site
* @param memento the IViewPart state or null if there is no previous saved state
* @exception PartInitException if this view was not initialized successfully
*/
public void init(IViewSite site, IMemento memento) throws PartInitException;
/** *//**
* Saves the object state within a memento.
*
* @param memento a memento to receive the object state
*/
public void saveState(IMemento memento);
这二个方法就是实现界面状态持久化的关键,注意saveState方法是在IPersistable接口中定义的。这些我们暂时忽略,主要是看如何使用这些机制。
如果去看JDT的实现或是org.eclipse.ui.ide一些视图的实现,你可以发现一些比较常用的实现形式。下面先看一段示例
Java代码
private IMemento fmemento;
/**//* 视图持久化状态标识 */
private static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
private static final String TAG_EXPANDED = "expanded"; //$NON-NLS-1$
private static final String TAG_ELEMENT = "element";//$NON-NLS-1$
private static final String TAG_PATH = "path"; //$NON-NLS-1$
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.fmemento = memento;
}
private IMemento fmemento;
/**//* 视图持久化状态标识 */
private static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
private static final String TAG_EXPANDED = "expanded"; //$NON-NLS-1$
private static final String TAG_ELEMENT = "element";//$NON-NLS-1$
private static final String TAG_PATH = "path"; //$NON-NLS-1$
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.fmemento = memento;
}
这是重写你自定义视图的init方法,定义一个全局的IMemento对象,初始化的时候为它赋值。并定义一系列的标识常量,用来表示你要保存的数据的标识。这一点与IDialogSettings是一致的。
下面是保存视图实现代码,如果你第一次接触可能有点晕,不过没关系,熟悉了以后你会发现Eclipse的内部实现也是类似的。下面的代码就是从Eclipse里面改过来的。
Java代码
/** *//**
* 保存视图状态
* <p>在此没有过滤和排序功能,所以只要保存展开节点的状态和选中节点的状态就够了</p>
*/
public void saveState(IMemento memento) {
System.out.println("保存视图");
//save visible expanded elements
Object expandedElements[] = viewer.getVisibleExpandedElements();
if (expandedElements.length > 0) {
IMemento expandedMem = memento.createChild(TAG_EXPANDED);
for (int i = 0; i < expandedElements.length; i++) {
if (expandedElements[i] instanceof ITestNode) {
System.out.println("展开元素 " +((ITestNode)expandedElements[i]).getPath());
IMemento elementMem = expandedMem
.createChild(TAG_ELEMENT);
elementMem.putString(TAG_PATH,
((ITestNode) expandedElements[i]).getPath());
}
}
}
//save selection
Object elements[] = ((IStructuredSelection) viewer.getSelection())
.toArray();
if (elements.length > 0) {
IMemento selectionMem = memento.createChild(TAG_SELECTION);
for (int i = 0; i < elements.length; i++) {
if (elements[i] instanceof ITestNode) {
System.out.println("选中元素 " +((ITestNode)elements[i]).getPath());
IMemento elementMem = selectionMem
.createChild(TAG_ELEMENT);
elementMem.putString(TAG_PATH,
((ITestNode) elements[i]).getPath());
}
}
}
System.out.println("保存视图完成");
}
/** *//**
* 保存视图状态
* <p>在此没有过滤和排序功能,所以只要保存展开节点的状态和选中节点的状态就够了</p>
*/
public void saveState(IMemento memento) {
System.out.println("保存视图");
//save visible expanded elements
Object expandedElements[] = viewer.getVisibleExpandedElements();
if (expandedElements.length > 0) {
IMemento expandedMem = memento.createChild(TAG_EXPANDED);
for (int i = 0; i < expandedElements.length; i++) {
if (expandedElements[i] instanceof ITestNode) {
System.out.println("展开元素 " +((ITestNode)expandedElements[i]).getPath());
IMemento elementMem = expandedMem
.createChild(TAG_ELEMENT);
elementMem.putString(TAG_PATH,
((ITestNode) expandedElements[i]).getPath());
}
}
}
//save selection
Object elements[] = ((IStructuredSelection) viewer.getSelection())
.toArray();
if (elements.length > 0) {
IMemento selectionMem = memento.createChild(TAG_SELECTION);
for (int i = 0; i < elements.length; i++) {
if (elements[i] instanceof ITestNode) {
System.out.println("选中元素 " +((ITestNode)elements[i]).getPath());
IMemento elementMem = selectionMem
.createChild(TAG_ELEMENT);
elementMem.putString(TAG_PATH,
((ITestNode) elements[i]).getPath());
}
}
}
System.out.println("保存视图完成");
}
要保存的数据是key--value形式,可以定义Boolean Integer Float String等基本类型对应的值,这些值就以key--value形式持久化到文件中。
上面的实现内容其实就是把视图中的树组件中的二部分状态转换成数据:展开元素和被选中元素。通过把它们转换成String类型(其实就是树路径)保存起来。IMemento的具体用法请查找Eclipse帮助文档。
完成了保存,下面我们看如何重新把数据取出来,使得打开的时候还原之前关闭时的状态。
init()方法调用的时候界面控件是还没有被创建的,所以不能在init()方法中添加还原的方法,应用在控件都创建完成后还原。
Java代码
/** *//**
* 创建视图的内容面板
*/
public void createPartControl(Composite parent) {
..
if (fmemento != null) {
System.out.println("开始还原");
restoreState(fmemento);
}
fmemento = null;
..
}
/** *//**
* 创建视图的内容面板
*/
public void createPartControl(Composite parent) {
..
if (fmemento != null) {
System.out.println("开始还原");
restoreState(fmemento);
}
fmemento = null;
..
}
完成控件创建后就调用restoreState方法,这是我们自定义的用于还原视图状态的方法。下面看一下,内容基本上就是saveState方法的逆向。
Java代码
/** *//**
* 还原视图的状态
* @param memento
*/
private void restoreState(IMemento memento) {
System.out.println("还原视图");
WorkSpaceNode wsn = (WorkSpaceNode)viewer.getInput();
IMemento childMem = memento.getChild(TAG_EXPANDED);
if (childMem != null) {
ArrayList elements = new ArrayList();
IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT);
for (int i = 0; i < elementMem.length; i++) {
System.out.println("还原展开路径 " + elementMem[i].getString(TAG_PATH));
Object element = NodeUtil.findNodeByPath(elementMem[i]
.getString(TAG_PATH), wsn);
System.out.println("还原展开节点 " + element);
if (element != null) {
elements.add(element);
}
}
viewer.setExpandedElements(elements.toArray());
}
childMem = memento.getChild(TAG_SELECTION);
if (childMem != null) {
ArrayList list = new ArrayList();
IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT);
for (int i = 0; i < elementMem.length; i++) {
Object element = NodeUtil.findNodeByPath(elementMem[i]
.getString(TAG_PATH), wsn);
if (element != null) {
list.add(element);
}
}
viewer.setSelection(new StructuredSelection(list));
}
System.out.println("还原视图完成");
}
/** *//**
* 还原视图的状态
* @param memento
*/
private void restoreState(IMemento memento) {
System.out.println("还原视图");
WorkSpaceNode wsn = (WorkSpaceNode)viewer.getInput();
IMemento childMem = memento.getChild(TAG_EXPANDED);
if (childMem != null) {
ArrayList elements = new ArrayList();
IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT);
for (int i = 0; i < elementMem.length; i++) {
System.out.println("还原展开路径 " + elementMem[i].getString(TAG_PATH));
Object element = NodeUtil.findNodeByPath(elementMem[i]
.getString(TAG_PATH), wsn);
System.out.println("还原展开节点 " + element);
if (element != null) {
elements.add(element);
}
}
viewer.setExpandedElements(elements.toArray());
}
childMem = memento.getChild(TAG_SELECTION);
if (childMem != null) {
ArrayList list = new ArrayList();
IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT);
for (int i = 0; i < elementMem.length; i++) {
Object element = NodeUtil.findNodeByPath(elementMem[i]
.getString(TAG_PATH), wsn);
if (element != null) {
list.add(element);
}
}
viewer.setSelection(new StructuredSelection(list));
}
System.out.println("还原视图完成");
}
这些工作就可以完成视图状态的保存与还原,还有一个特别要注意的地方,你必须对插件的WorkbenchAdvisor类的public void initialize(IWorkbenchConfigurer configurer)方法进行重写,添加configurer.setSaveAndRestore(true);这个方法就可以打开保存机制。如果没有这个步骤,上面的工作不会起任何效果。
GUI状态的持久化都保存在运行时生成的.metadata\.plugins目录下的xml文件,你可以手动去打开这些文件查看数据结果是否跟你预期的一样。IEditorPart以及Perspective和其它的全局信息持久化的也是同样的原理。只是复杂度不一样。建议可以查看org.eclipse.ui.ide中的实现原理。
分享到:
相关推荐
7. **持久化状态**:为了保存用户设置和编辑器的状态,你需要实现`IPersistableEditorContributor`接口,确保编辑器可以正确地保存和恢复其状态。 在"rpcTest"这个压缩包中,很可能是包含了上述这些组件的实现代码...
- 编辑器是RCP中处理文档或数据的主要界面,它们可以是可保存和可恢复状态的。通过继承`EditorPart`类并实现相关方法,可以创建自定义编辑器。 8. 外部JAR的使用 - 在RCP项目中,可以引入外部JAR库以扩展功能或...
这里我们详细探讨如何解决标题中提到的问题,包括窗口居中、大小固定、标题文字设置、闪屏画面、窗口状态保存、窗口样式定制以及窗口自动居中。 首先,针对描述中提到的主界面问题,我们需要对窗口的属性进行调整。...
理解这些机制可以帮助你在应用中保存和恢复用户状态。 9. **扩展点与扩展**:RCP的灵活性体现在其强大的插件系统,通过定义扩展点(Extension Point),其他插件可以对其进行扩展。学习如何创建和使用扩展点能让你...
- **添加自定义视图**:指导创建和集成自定义视图到RCP环境中。 - **向VIEW里添加ACTION**:在视图中添加操作,增强视图功能。 6. **编辑器** - **概述**:解释编辑器在RCP中的角色,作为用户界面的一部分用于...
9. **RCP应用生命周期**:理解从启动到关闭的整个应用程序生命周期,包括初始化、保存和恢复状态、事件处理等。 10. **Extension Points**:这是Eclipse插件系统的关键特性,允许开发者通过定义和实现扩展点来扩展...
5. **持久化存储**:使用Persistence Service保存和恢复应用程序状态。 6. **自定义进度条与对话框**:通过Job类实现后台任务的异步执行,并展示进度信息。 7. **插件通信**:使用服务定位器(Service Locator)或...
- **向你的程序添加错误日志视图**: 创建视图贡献至UI以显示错误日志。 #### 15. 产品 - **概述**: 构建可分发的Eclipse RCP应用。 - **PRODUCT配置文件**: - 定义产品的启动配置。 - 设置启动类、产品ID等。 - *...
透视图是Eclipse IDE和基于RCP的应用程序中的一个重要组成部分,它定义了工作台窗口中显示的视图、编辑器和其他组件的布局。在RCP开发中,透视图允许用户根据他们的工作需求定制和组织界面。 在描述中提到的博文...
- **共享状态行**:多个视图可以共享同一个状态行,以显示状态信息。 #### 二十、技巧与窍门 ##### 21.1 保存用户布局 - **自动保存**:自动保存用户的界面布局,以便下次启动时恢复。 ##### 21.2 查找未使用的...
- 使用Preference Service保存用户偏好和应用状态,使得应用在下次启动时能恢复上次的状态。 - 数据持久化可以借助于PDE提供的API,如`org.eclipse.core.runtime.preferences`包。 7. **集成开发环境(IDE)特性*...
2. **模型-视图-控制器(MVC)模式**:Eclipse RCP应用通常遵循MVC设计模式,其中模型表示数据,视图负责展示数据,而控制器处理用户交互。在编辑器开发中,模型可能包括解析和存储文件内容的对象,视图则负责渲染...
2. **模型(Model)**:模型存储应用程序的数据和状态,它是视图和控制器之间的数据交换媒介。Java RCP支持MVC(Model-View-Controller)设计模式,确保数据的独立性和一致性。 3. **控制器(Controller)**:控制器...
### RCP 开发自学教程知识点总结 #### 一、富客户端平台(RCP) **1.1 概述** - **Eclipse RCP (Rich Client Platform)**: 是一款强大的开源框架,用于开发桌面应用,它提供了丰富的组件和工具,使得开发者能够轻松...
5. **视图(View)**和**编辑器(Editor)**:视图提供了应用程序状态的可视化展示,如项目浏览器、问题视图等;编辑器则用于编辑和显示具体类型的文件,如源代码编辑器。 6. **活动(Action)**和**命令(Command...
6. **持久化和偏好设置**:RCP支持用户界面的自定义和保存状态。你需要学习如何使用Preference Store来存储用户偏好设置,以及如何利用State Persistence来保存和恢复应用的状态。 7. **调试和测试**:掌握Eclipse...
2. **Advisor类**:包括`ApplicationActionBarAdvisor`、`ApplicationWorkbenchAdvisor`和`ApplicationWorkbenchWindowAdvisor`,这些顾问类对RCP应用的界面元素如菜单栏、工具栏和状态栏进行定制,是控制用户体验的...
10. **持久化(Persistence)**:Eclipse RCP提供了持久化服务,用于保存和恢复应用状态。理解如何利用这项服务对用户体验至关重要。 11. **调试与测试**:Eclipse RCP工具集包括强大的调试器,方便开发者测试和...
通过深入学习和实践,你将能够熟练掌握RCP插件开发技术,构建出功能丰富、用户体验优秀的桌面应用程序。本教程的PDF文档"RCP Plug-in开发自学教程(CEC首发)"将详细讲解这些知识点,是自学RCP开发的宝贵资料。
- **视图(Views)**:展示数据和功能的界面元素,每个视图都有自己的生命周期和状态。 - **命令(Commands)**:用于封装用户操作的行为,如打开文件、保存等,支持动态绑定和国际化。 - **消息和图标(Messages ...