`
Jet_Geng
  • 浏览: 55495 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

在Eclipse RCP应用程序中使用Databinding(邦定)

阅读更多


1. Eclipse Databinding概述

Eclipse Databinding可以在你的模型和用户界面之间建立一种关联。当任何一方(模型或用户界面)发生变化时,都可以同步到另一方。 另外你可以使用默认的或者是自定义的数据验证器(validator)来验证数据同时可以使用转换器(converter)在模型和界面之间转换数据。 下面我们用一个应用程序来演示Databinding功能。在这个程序中我们在界面中显示一个Person对象,用户可以在界面中修改Person对象的值。 也可以通过一个按钮来触发事件来直接修改模型。任何一端的变化都会同步到另一端。

1.  Domain Model

1.1.  概述

首先创建一个可复用的数据模型。所以我们把数据模型封装到一个独立的插件(plugin)中以方便复用。

 

1.2.  创建插件

创建一个名为“de.vogella.databinding.person.model”的插件项目。不要创建activator,不要选这“This plug-in will make contributions to th UI”,也不要选择“Do you want to create a rich client application”.

 

点击"Finish". 为了能够在用户界面和模型之间直接使用Databinding,模型必须实现PropertyChangeSupport接口。这样Eclipse Databinding框架就可以监听到在模型中的变化了。 创建一个名为 de.vogella.databinding.person.model 和如下的文件。

package de.vogella.databinding.person.model;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Person implements PropertyChangeListener {
	private String firstName;
	private String lastName;
	private boolean married;
	private String gender;
	private Integer age;
	private Address address;
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	public Person() {
	}

	public void addPropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public String getFirstName() {
		return firstName;
	}

	public String getGender() {
		return gender;
	}

	public String getLastName() {
		return lastName;
	}

	public boolean isMarried() {
		return married;
	}

	public void setFirstName(String firstName) {
		propertyChangeSupport.firePropertyChange("firstName", this.firstName,
				this.firstName = firstName);
	}

	public void setGender(String gender) {
		propertyChangeSupport.firePropertyChange("gender", this.gender,
				this.gender = gender);
	}

	public void setLastName(String lastName) {
		propertyChangeSupport.firePropertyChange("lastName", this.lastName,
				this.lastName = lastName);
	}

	public void setMarried(boolean isMarried) {
		propertyChangeSupport.firePropertyChange("married", this.married,
				this.married = isMarried);
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		propertyChangeSupport.firePropertyChange("age", this.age,
				this.age = age);
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		address.addPropertyChangeListener("country", this);
		propertyChangeSupport.firePropertyChange("address", this.address,
				this.address = address);
	}

	@Override
	public String toString() {
		return firstName + " " + lastName;
	}

	@Override
	public void propertyChange(PropertyChangeEvent event) {
		propertyChangeSupport.firePropertyChange("address", null, address);
	}

}
				
				


 
package de.vogella.databinding.person.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Address {

	private String street;
	private String number;
	private String postalCode;
	private String city;
	private String country;
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	public void addPropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public Address() {
	}

	public Address(String postalCode, String city, String country) {
		this.postalCode = postalCode;
		this.city = city;
		this.country = country;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		propertyChangeSupport.firePropertyChange("street", this.street,
				this.street = street);
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		propertyChangeSupport.firePropertyChange("number", this.number,
				this.number = number);
	}

	public String getPostalCode() {
		return postalCode;
	}

	public void setPostalCode(String postalCode) {
		propertyChangeSupport.firePropertyChange("postalCode", this.postalCode,
				this.postalCode = postalCode);
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		propertyChangeSupport.firePropertyChange("citry", this.city,
				this.city = city);
		this.city = city;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		propertyChangeSupport.firePropertyChange("country", this.country,
				this.country = country);
	}

	public String toString() {
		String s = "";
		s += street != null ? street + " " : "";
		s += number != null ? number + " " : "";
		s += postalCode != null ? postalCode + " " : "";
		s += city != null ? city + " " : "";
		s += country != null ? country + " " : "";

		return s;
	}

}
 

打开 META-INF 文件夹中的 MANIFEST.MF 文件。选中"Runtime"选项页。把 de.vogella.databinding.person.model 加入到 Exported Packages 中。这样其他插件就可以访问到这个包了。

2. 绑定到SWT控件

2.1.  RCP项目

通过“Hello RCP”模板创建一个名为“de.vogella.databinding.person.swt”的Eclipse RCP项目(具体的可以参考 Create your first Eclipse RCP )。

2.2. 依赖模块

把“de.vogella.databinding.person.model”插件添加到当前项目的依赖中。

2.3.  添加Eclipse Databinding的依赖

把"org.eclipse.core.databinding", "org.eclipse.core.databinding.beans", "org.eclipse.jface.databinding" 和 "org.eclipse.core.databinding.property" 添加到当前项目的依赖中。

2.4.  用户界面

向当前RCP项目添加一个视图(view),并创建这个视图的实现类 “de.vogella.databinding.person.PersonView ” 把这个视图添加到透视图中去。(可以参考 Eclipse RCP Tutorial ) 实现代码如下所示

package de.vogella.databinding.person.swt;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.databinding.person.model.Address;
import de.vogella.databinding.person.model.Person;

public class PersonView extends ViewPart {
	public static final String ID = "de.vogella.databinding.person.swt.View";
	private Person person;

	private Text firstName;
	private Text ageText;
	private Button marriedButton;
	private Combo genderCombo;
	private Text countryText;

	public PersonView() {
	}

	@Override
	public void createPartControl(Composite parent) {

		person = new Person();
		Address address = new Address();
		address.setCountry("Deutschland");
		person.setAddress(address);
		person.setFirstName("John");
		person.setLastName("Doo");
		person.setGender("Male");
		person.setAge(12);
		person.setMarried(true);
		// Lets put thing to order
		Layout layout = new GridLayout(2, false);
		parent.setLayout(layout);

		Label firstLabel = new Label(parent, SWT.NONE);
		firstLabel.setText("Firstname: ");
		firstName = new Text(parent, SWT.BORDER);

		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		firstName.setLayoutData(gridData);

		Label ageLabel = new Label(parent, SWT.NONE);
		ageLabel.setText("Age: ");
		ageText = new Text(parent, SWT.BORDER);

		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		ageText.setLayoutData(gridData);

		Label marriedLabel = new Label(parent, SWT.NONE);
		marriedLabel.setText("Married: ");
		marriedButton = new Button(parent, SWT.CHECK);

		Label genderLabel = new Label(parent, SWT.NONE);
		genderLabel.setText("Gender: ");
		genderCombo = new Combo(parent, SWT.NONE);
		genderCombo.add("Male");
		genderCombo.add("Female");

		Label countryLabel = new Label(parent, SWT.NONE);
		countryLabel.setText("Country");
		countryText = new Text(parent, SWT.BORDER);

		Button button1 = new Button(parent, SWT.PUSH);
		button1.setText("Write model");
		button1.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				System.out.println("Firstname: " + person.getFirstName());
				System.out.println("Age " + person.getAge());
				System.out.println("Married: " + person.isMarried());
				System.out.println("Gender: " + person.getGender());
				System.out.println("Country: "
						+ person.getAddress().getCountry());
			}
		});

		Button button2 = new Button(parent, SWT.PUSH);
		button2.setText("Change model");
		button2.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				person.setFirstName("Lars");
				person.setAge(person.getAge() + 1);
				person.setMarried(!person.isMarried());
				if (person.getGender().equals("Male")) {

				} else {
					person.setGender("Male");
				}
				if (person.getAddress().getCountry().equals("Deutschland")) {
					person.getAddress().setCountry("USA");
				} else {
					person.getAddress().setCountry("Deutschland");
				}
			}
		});

		// Now lets do the binding
		bindValues();
	}

	@Override
	public void setFocus() {
	}

	private void bindValues() {
		// The DataBindingContext object will manage the databindings
		DataBindingContext bindingContext = new DataBindingContext();
		IObservableValue uiElement;
		IObservableValue modelElement;
		// Lets bind it
		uiElement = SWTObservables.observeText(firstName, SWT.Modify);
		modelElement = BeansObservables.observeValue(person, "firstName");
		// The bindValue method call binds the text element with the model
		bindingContext.bindValue(uiElement, modelElement, null, null);

		uiElement = SWTObservables.observeText(ageText, SWT.Modify);
		modelElement = BeansObservables.observeValue(person, "age");
		// Remember the binding so that we can listen to validator problems
		// See below for usage
		bindingContext.bindValue(uiElement, modelElement, null, null);

		uiElement = SWTObservables.observeSelection(marriedButton);
		modelElement = BeansObservables.observeValue(person, "married");

		bindingContext.bindValue(uiElement, modelElement, null, null);

		uiElement = SWTObservables.observeSelection(genderCombo);
		modelElement = BeansObservables.observeValue(person, "gender");

		bindingContext.bindValue(uiElement, modelElement, null, null);

		// Address field is bound to the Ui
		uiElement = SWTObservables.observeText(countryText, SWT.Modify);
		modelElement = BeanProperties.value("address.country").observe(person);
		bindingContext.bindValue(uiElement, modelElement, null, null);

	}

}
			
 

DataBindingContext对象用来管理绑定。通过调用bindValue方法将界面上的text元素和模型绑定。第一个参数是 uiElement他把一个更新策略封装到一个IObservableValue对象中,第二个参数和第一个参数一样唯一不同的是他封装的是一个模型对 象。可以通过最后两个参数把验证器(validator)和转换器(converter)传给DataBindingContext.如果传入的是 null,将会使用默认的。

2.5.  Run

运行以上程序。每当你在用户界面中修改时,模型将会被同步。如果你直接修改模型时,用户界面将会同时被更新。 上面的代码同时还演示了Eclipse Databinding预定义的转换器和验证器。

Note

默认情况下text控件用 “text ” 属性来邦定到模型的属性。用户也可以指定用其他属性来邦定到模型属性。 例如:用户可以将控件中的 “enabled ” 邦定到一个布尔(boolean)类型的模型属性(模型中的字段)。

 

3.  JFace 邦定

3.1.  概述

JFace提供了一个高扩展的数据和表现分离的机制。下面将重点讨论如何在JFace中使用Eclipse Databinding。 关于JFace的例子可以参考 JFace Tables With Eclipse RCP

下面将演示一下在list(ListViewer),table(TableViewer)和tree (TreeViewer)viewer中使用Eclipse Databinding。

添加一个视图。实现类代码如下。

package de.vogella.databinding.person.listviewer;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import de.vogella.databinding.person.model.Person;

public class View extends ViewPart {

	private ListViewer viewer;
	private WritableList input;

	@Override
	public void createPartControl(Composite parent) {
		// Just a little bit layout
		parent.setLayout(new GridLayout(3, false));

		// Define the viewer
		viewer = new ListViewer(parent);
		viewer.setContentProvider(new ObservableListContentProvider());
		List<Person> persons = new ArrayList<Person>();
		// Just for testing we create sample data
		createExampleData(persons);
		input = new WritableList(persons, Person.class);
		// Set the writeableList as input for the viewer
		viewer.setInput(input);

		Button delete = new Button(parent, SWT.PUSH);
		delete.setText("Delete");
		delete.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (!viewer.getSelection().isEmpty()) {
					IStructuredSelection selection = (IStructuredSelection) viewer
							.getSelection();
					Person p = (Person) selection.getFirstElement();
					input.remove(p);
				}
			}
		});

		Button add = new Button(parent, SWT.PUSH);
		add.setText("Add");
		add.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				Person p = new Person();
				p.setFirstName("Test");
				p.setLastName("Test");
				input.add(p);
			}
		});
	}

	protected void createExampleData(List<Person> persons) {
		Person p = new Person();
		p.setFirstName("Joe");
		p.setLastName("Darcey");
		persons.add(p);
		p = new Person();
		p.setFirstName("Jim");
		p.setLastName("Knopf");
		persons.add(p);
		p = new Person();
		p.setFirstName("Jim");
		p.setLastName("Bean");
		persons.add(p);
	}

	@Override
	public void setFocus() {

	}

}
 

在这个例子中界面将变成如下的样子。当你添加和修改模型的时候用户界面也会跟着一起更新。

 

 

 

注:英文原文为 Eclipse Databinding with Eclipse RCP applications - Tutorial

      还有一部分没有翻译完。后续马上跟上。

 

  • 大小: 9.7 KB
  • 大小: 16.5 KB
  • 大小: 19.1 KB
  • 大小: 8.3 KB
  • 大小: 580 Bytes
0
0
分享到:
评论

相关推荐

    开发您的第一个 Eclipse RCP 应用程序

    2. **新建 RCP 应用程序项目**:选择 "File" &gt; "New" &gt; "Other",然后在 "Project" 分类中找到 "Eclipse Application" 并点击 "Next"。 3. **配置项目**:输入项目名称(例如 "HelloWorldRCP"),选择所需的模板,并...

    eclipse rcp应用系统开发方法与实战源代码.zip

    3. **工作台管理**:工作台是Eclipse RCP中的核心,它管理着应用程序的用户界面。开发者要学会如何创建和管理透视图,以及在透视图中添加视图和编辑器。 4. **视图和编辑器**:视图提供信息展示,编辑器则用于数据...

    EclipseRcp 例子程序

    通过对“Eclipse RCP 例子程序”的深入学习和实践,开发者不仅可以掌握Eclipse RCP的基本使用,还能了解到如何构建复杂、可扩展的桌面应用程序。而"Hyperbola"可能是指一个具体的示例项目或者一个用于演示特定功能的...

    ECLIPSE+RCP应用系统开发方法与实战(PDF 高岗著)

    Eclipse RCP是Eclipse IDE的一部分,它提供了一个框架,使得开发者可以构建功能丰富的、可定制的桌面应用程序。以下是对该书可能涉及的知识点的详细阐述: 1. **Eclipse RCP基础**:首先,书中会介绍Eclipse RCP的...

    Eclipse RCP 软件打包发布方法

    1. **新建“产品配置”**:在Eclipse中,你需要通过"File" -&gt; "New" -&gt; "Other" -&gt; "Plug-in Development" -&gt; "Product Configuration"来创建一个新的产品配置。这个配置定义了你的应用程序的基本属性,如应用程序的...

    开发你的第一个EclipseRCP应用程序汇编.pdf

    1. **创建项目**:在Eclipse中,开发者可以通过选择特定的RCP模板来初始化一个新的项目。 2. **定义工作台**:RCP应用程序的核心是工作台,开发者需要配置工作台的行为,如窗口布局和视图管理。 3. **添加视图和操作...

    Eclipse RCP中使用第三方包

    5.如何在RCP应用程序中使用第三方库中的类和方法? 答:可以使用第三方库中的类和方法来实现某些功能,例如使用Hello类中的sayHello方法来设置应用程序的标题。 6.什么是plugin的Build页面? 答:plugin的Build页面...

    Eclipse RCP 应用系统开发方法与实战

    Eclipse Rich Client Platform (RCP) 是一个强大的框架,用于构建桌面应用程序。它基于Java,提供了丰富的用户界面组件和插件机制,使得开发者能够构建功能丰富的、可扩展的应用程序。"Eclipse RCP 应用系统开发方法...

    Eclipse rcp深入浅出中英文版及配套代码

    Eclipse RCP,全称Eclipse Rich Client Platform,是一个基于Java的框架,用于构建桌面应用程序。这个框架由Eclipse基金会维护,是Eclipse IDE的一部分,允许开发者创建功能丰富的、可扩展的应用程序,拥有类似IDE的...

    Eclipse RCP 应用系统开发方法与实战 源代码

    Eclipse Rich Client Platform (RCP) 是一个强大的框架,用于构建桌面应用程序,它基于Java,提供了丰富的用户界面组件和强大的插件系统。本资源提供的"《Eclipse RCP 应用系统开发方法与实战 源代码》"是针对...

    Eclipse RCP应用系统开发方法与实战(源代码)

    Eclipse Rich Client Platform (RCP) 是一个强大的框架,用于构建桌面应用程序。它基于Java,提供了丰富的用户界面组件和插件机制,使得开发者能够构建功能丰富的、可扩展的应用程序。本资源提供了"Eclipse RCP应用...

    使用Eclipse RCP进行桌面程序开发

    **Eclipse RCP** (Rich Client Platform) 是一种基于Java的开源框架,用于开发桌面应用程序。自从Eclipse 3.0版本以来,RCP逐渐成为构建高度定制化、功能丰富的桌面应用的标准平台之一。 **快速起步步骤**: 1. **...

    EclipseRCP教程

    Eclipse RCP(Rich Client Platform)是一种基于 Eclipse 平台的客户端开发技术,能够帮助开发者快速构建功能强大且界面美观的桌面应用程序。在本教程中,我们将详细介绍 Eclipse RCP 的开发过程、技术要点和注意...

    Eclipse RCP.pdf清晰版

    1. **创建新的Eclipse插件项目**: 在Eclipse中选择File -&gt; New -&gt; Other -&gt; Plug-in Project。 2. **定义插件元数据**: 描述插件的基本信息,如名称、ID、版本号等。 3. **实现功能**: 开发插件的核心逻辑和用户界面...

    Eclipse Rcp

    Eclipse RCP是一种基于Eclipse平台的富客户端平台技术,它允许开发者创建独立于Eclipse环境的Java桌面应用程序。RCP通过提供一套标准组件和API,简化了桌面应用程序的开发流程,使开发者能够专注于业务逻辑而非界面...

    eclipse rcp经典程序

    Eclipse RCP(Rich Client Platform)是Eclipse框架下的一个应用程序开发平台,它提供了一种构建桌面应用的强大工具集。Eclipse RCP程序通常由多个组件构成,包括视图(Views)、编辑器(Editors)、透视图...

    eclipse rcp应用系统开发方法与实战

    总的来说,这个项目将带你深入Eclipse RCP的世界,通过实际操作,你可以提升在桌面应用开发领域的技能,理解如何利用Eclipse RCP的特性来构建强大且灵活的应用程序。在完成这个项目后,你将具备独立设计、开发和维护...

    在Eclipse RCP中应用Spring OSGI 管理bean(一)

    标题中的“在Eclipse RCP中应用Spring OSGI 管理bean(一)”表明这是一篇关于如何在Eclipse Rich Client Platform (RCP)应用程序中集成Spring框架,并利用OSGi服务来管理Bean的教程。Eclipse RCP是一个用于构建桌面...

    Eclipse RCP应用系统开发

    总的来说,Eclipse RCP是现代软件开发中的一个强大工具,尤其适合那些需要桌面级应用程序的企业或项目。掌握Eclipse RCP开发技术,不仅能够提升个人技能,还能适应快速变化的IT市场,为职业生涯开辟更多可能性。同时...

Global site tag (gtag.js) - Google Analytics