Eclipse设计实现可重用的SWT构件
2007-11-19 10:44:36 来源:论坛整理 作者:翁长河 点击:
本文从创建一个简单的SWT Tree Table开始,引入可重用的用户界面构件这个开发人员普遍关心的问题,然后分析Eclipse的用户界面的一些设计模式,循序渐进的向读者展示了如何设计实现一个精巧的高度可重用的TreeTable构件,最终通过增加一些扩展的功能显示了该构件强大的可扩展能力和灵活性。
本文从创建一个简单的SWT Tree Table开始,引入可重用的用户界面构件这个开发人员普遍关心的问题,然后分析Eclipse的用户界面的一些设计模式,循序渐进的向读者展示了如何设计实现一个精巧的高度可重用的TreeTable构件,最终通过增加一些扩展的功能显示了该构件强大的可扩展能力和灵活性。读者将能够了解到如何在SWT程序中设计实现可重用的构件,以减少重复的用户界面程序的工作量,降低因为需求变化所引起的风险和程序的维护成本。
1. 问题的起源
我们经常困惑于在不同的项目中重复的编写看上去很相似的代码,有时候会感觉自己只是一个体力劳动者,每天重复的编写着看上去很酷的程序。尤其是在用户界面编程中,拷贝粘贴成了家常便饭,那些迷人的SWT界面其实并没有给你带来什么热情。是的,你需要改变,让生活重新回复光彩,找到第一次写出“HelloWord”的美好感觉。本文将向您展示如何实现灵活可扩展的SWT构件,本文所有的代码在Eclipse3.2.1平台上通过测试。
我们从这样一个问题开始,假设我们在一个基于Eclipse的RCP项目中,需要创建一个表格,用于显示员工信息。这个RCP项目会有很多个类似的表格,我们首先实现一个示例研究一下如何更好的设计用户界面。该表格是要显示一组按部门分组的员工,每个部门会有多个经理,每个经理管辖多个员工。因此我们要构建一个Tree Table,会有不同的列来显示不同的属性,而行的数据可能有3类:部门,经理,员工。我们设计这样的问题具有典型的代表性,Eclipse RCP应用中经常需要面对这样的情况。这是一个虚构的例子,与任何具体的应用无关,本文的代码只是作为示例使用。
图1展示了模型部分的3个类:Department,Manager和Employee,详细的代码参见附件中的源代码。
图1:Tree Table示例的数据模型

构建一个简单的Tree Table
使用SWT和JFace的构件,我们可以很容易的构造出一个展示图1中的模型的Tree Table演示程序,该演示程序主要包含3个类:EmployeeContentProvider和EmployeeLabelProvider,SimpleTestWindow。
如清单1所示,EmployeeContentProvider负责向TreeTable提供内容。
清单1:EmployeeContentProvider的代码。
public class EmployeeContentProvider extends ArrayContentProvider
implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof Manager&((Manager)parentElement).getMembers()!=null)
return ((Manager)parentElement).getMembers().toArray();
else if(parentElement instanceof Department)
return ((Department)parentElement).getEmployees().toArray();
return new Object[0];
}
public Object getParent(Object element) {
return null;
}
public boolean hasChildren(Object element) {
return getChildren(element).length>0;
}
} |
如清单2所示,EmployeeLabelProvider主要负责为每行的每一列显示Image和Text。
清单2:EmployeeLabelProvider的代码。
public class EmployeeLabelProvider extends LabelProvider implements ITableLabelProvider{
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
if(element instanceof Department&& columnIndex ==0)
return ((Department)element).getName();
else if(element instanceof Employee)
{
if(columnIndex ==0)
return ((Employee)element).getName();
else if (columnIndex ==1) {
if(element instanceof Manager)
return "Manager";
else
return "Employee";
}
else if (columnIndex ==2)
return ((Employee)element).getTelephone();
else if (columnIndex ==3)
return ((Employee)element).getBirthday();
}
return "";
}
} |