首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

14.2  创建表格并显示数据

作为起步,本节将演示如何创建一个TableViewer对象,如何用TableViewer来显示数据记录,实例运行效果如图14.3所示。

图14.3  TableViewer效果图

14.2.1  实例的数据模型介绍

本实例用TableViewer来显示一个数据表中的3条记录,每一条记录对应某一个人的基本资料,记录有5个字段:ID号(数值型)、姓名(字符型)、性别(布尔型)、年龄(数值型)和记录建立时间(日期型)。

如何在程序中体现和操作这些数据记录呢?在过去,像ASP、PHP这类面向过程的编程模式,人们习惯了这样操作数据:从数据库中读取数据,并不对数据做任何封装,直接将数据一条条地显示在表格中。

现在用Java这种面向对象的编程语言,应该用更规范的方式来操作数据:将数据库中的记录看作一个数据对象,用一个类来表示它,数据表的字段写成类的实例变量,这样的类在Java中叫做实体类(或称数据类)。EJB和Hibernate的数据操作方式都是这样的。

数据库与表格显示之间加上了实体类,如此一来,以前的“数据表→表格显示”方式就分成了两个步骤“数据库→实体类→表格显示”。有些习惯了以前编程方式的人也许会觉得多了一个步骤太麻烦,但其实这种方式很有好处:

  ● 表格显示的代码不再和数据库表相关。例如,将数据库由Oracle移植到MySQL时就不需要更改“数据库→实体类”这个环节的代码。

  ● 零散的字段变量统一在一个类中,程序代码结构更紧凑、清晰,有利于今后代码的维护。不要小看维护问题,很多系统做好后不敢再改,害怕改动后会牵涉到其他模块,其中原因之一就是代码结构太乱、编程不规范所致。

  ● 将数据封装在一个实体类中,在数据传递时方便许多,可以将实体类作为一个参数在方法与方法之间来回传递。

14.2.2  创建数据表的实体类

下面依照表中的字段来创建一个相应的实体类,类名为PeopleEntity,代码如下所示。

//------------- 文件名:PeopleEntity.java --------------

// 本类包含5个不同数据类型的变量,分别对应数据库表中的5个字段。变量为private型,即只能

// 由类的内部代码访问,外界只能通过这些变量相应的Setter/Getter方法来访问它们

public class PeopleEntity {

    private Long id; //唯一识别码,在数据库里常为自动递增的ID列

    private String name; //姓名

    private boolean sex; //性别 true男,flase女

    private int age; //年龄

    private Date createDate; //记录的建立日期。Date类型是java.util.Date,而不是java.sql.Date

    //以下代码为字段各自的Setter/Getter方法。参考第3.5.2节,这些方法在Eclipse可自动生成

         public Long getId() { return id;}

         public void setId(Long long1) {id = long1;}

         public String getName() {return name;}

         public void setName(String string) {name = string;}

         public boolean isSex() { return sex;}

         public void setSex(boolean sex) { this.sex = sex; }

         public int getAge() {return age;}

         public void setAge(int i) {age = i;}

         public Date getCreateDate() {return createDate;}

         public void setCreateDate(Date date) {createDate = date;}

}

14.2.3  数据的生成

由于数据操作是分两步走:“数据库→实体类→表格显示”,实体类隔离了代码对数据库的依赖,所以“数据库→实体类”这一步就不再讲解,这部分的代码与JFace组件的使用无关紧要,也不会影响表格组件的讲解。关于TableViewer和数据库结合使用方面的内容,在后面“插件项目实战”中会有详细示例。

那么如何生成实体类的对象呢?因为数据记录和实体对象相对应,新创建的实体对象就相当于一个空记录,可以用其set方法一个个地将值设入实体对象中,这样就能得到带有数据的实体对象了。

为了今后便于扩展,将创建实体对象的方法集中在一个类中,这种专门负责创建对象的类又叫对象工厂。此类的代码如下:

//-----------文件名:PeopleFactory.java ----------------

//创建PeopleEntity对象的工厂,创建3个PeopleEntry对象,并装入List集合返回

public class PeopleFactory {

         public static List<PeopleEntity> getPeoples() { // 工厂的静态方法

                   List<PeopleEntity> list = new ArrayList<PeopleEntity>();

                   { // 第1个实体类对象

                            PeopleEntity o = new PeopleEntity();

                            o.setId(new Long(1));// id字段的类型被定义成了Long,所以要转化一下

                            o.setName("陈刚");

                            o.setSex(true);

                            o.setAge(28);

                            o.setCreateDate(new Date()); // 当前日期

                            list.add(o);

                  }

                   { // 第2个实体类对象

                            PeopleEntity o = new PeopleEntity();

                            o.setId(2L); // 利用JDK5.0的自动装箱功能,省了long到Long对象的转化

                            o.setName("周阅");

                            o.setSex(false);

                            o.setAge(18);

                            o.setCreateDate(new Date());

                            list.add(o);

                   }

                   { // 第3个实体类对象

                            PeopleEntity o = new PeopleEntity();

                            o.setId(3L);

                            o.setName("陈常恩");

                            o.setSex(true);

                            o.setAge(27);

                            o.setCreateDate(new Date());

                            list.add(o);

                   }

                   return list;

         }

}

程序说明:

  ● 在实际应用中,getPeoples方法可由硬性生成PeopleEntity对象,改为从数据库中取出数据后生成PeopleEntity对象。

  ● 这里的List不是SWT组件的List,而是Java的集合类java.util.List。根据实际开发情况也可以用数组或Set、Map等代替List。

  ● List是接口,而ArrayList是实际用的类。由于其后代码是基于List接口编写的,所以换用其他List接口的实现类,如Vector、LinkedList等,而不必修改其后的代码。面向接口编程,尽量让定义类型(如List)比实际类型(如ArrayList)更宽泛些,有利于以后的修改维护。

  ● 这里new ArrayList<PeopleEntity>()使用了JDK5.0的泛型功能,关于泛型可参阅www.chengang.com.cn上的Java类文章。

  ● 在数据库编程中,Java集合类起着重要作用。一定要很熟悉各集合类在特性上的差别,这样才能根据实际开发情况作出适当的选择(集合类的详细资料可查阅Java基础书籍)。

14.2.4  在表格中显示数据

在得到由List装载的包含数据信息的实体类对象后,接下来就是使用TableViewer来显示这些数据,实现过程一般要经过如下步骤:

  ● 第一步:创建一个TableViewer对象,并在构造函数中用式样设置好表格的外观,这与其他SWT组件的用法一样。

  ● 第二步:通过表格内含的Table对象设置布局方式,一般都使用TableViewer的专用布局管理器TableLayout。该布局方式将用来管理表格内的其他组件(如TableColumn表格列)。

  ● 第三步:用TableColumn类创建表格列。

  ● 第四步:设置内容器和标签器。内容器和标签器是JFace组件中的重要概念,它们分别是IStructuredContentProvider、ITableLabelProvider两个接口的实现类,它们的作用就是定义好数据应该如何在TableViewer中显示。

  ● 第五步:用TableViewer的setInput方法将数据输入到表格。就像人的嘴巴,setInput就是TableViewer的嘴巴。

图14.4是TableViewer整个数据流程的示意图。

图14.4  TableViewer数据流程示意图

程序代码如下(内容器和标签器写成两个单独的类):

//-------------文件名:TableViewer1.java-------------------

shell.setLayout(new FillLayout());

// 第一步:创建一个TableViewer对象。式样:MULTI可多选、H_SCROLL有水平滚动条、V_SCROLL
// 有垂直滚动条、BORDER有边框、FULL_SELECTION整行选择

TableViewer tv=new TableViewer(shell, SWT.MULTI |SWT.BORDER |SWT.FULL_SELECTION);

// 第二步:通过表格内含的Table对象设置布局方式

Table table = tv.getTable();

table.setHeaderVisible(true); // 显示表头

table.setLinesVisible(true); // 显示表格线

TableLayout layout = new TableLayout(); // 专用于表格的布局

table.setLayout(layout);

// 第三步:用TableColumn类创建表格列

layout.addColumnData(new ColumnWeightData(13));// ID列宽13像素

new TableColumn(table, SWT.NONE).setText("ID号");

layout.addColumnData(new ColumnWeightData(40));

new TableColumn(table, SWT.NONE).setText("姓名");

layout.addColumnData(new ColumnWeightData(20));

new TableColumn(table, SWT.NONE).setText("性别");

layout.addColumnData(new ColumnWeightData(20));

new TableColumn(table, SWT.NONE).setText("年龄");

layout.addColumnData(new ColumnWeightData(60));

new TableColumn(table, SWT.NONE).setText("记录建立时间");

// 第四步:设置内容器和标签器

tv.setContentProvider(new TableViewerContentProvider());

tv.setLabelProvider(new TableViewerLabelProvider());

// 第五步:用TableViewer的setInput方法将数据输入到表格

Object data = PeopleFactory.getPeoples();

tv.setInput(data);

//-------------文件名:TableViewerContentProvider.java-------------------

//内容器。由此类对输入到表格的数据进行筛选和转化。此类要实现接口的3种方法,其中           //getElements是主要方法,另外两个方法很少用到,空实现就行了

public class TableViewerContentProvider implements IStructuredContentProvider {

         // 对输入到表格的数据集合进行筛选和转化。输入的数据集全部要转化成数组,每一个数组元素

         //就是一个实体类对象,也就是表格中的一条记录

         public Object[] getElements(Object element) {

                   // 参数element就是通过setInput(Object input)输入的对象input
                   // 本例中输入给setInput是List集合

                   if (element instanceof List)// 加一个List类型判断

                            return ((List) element).toArray(); // 将数据集List转化为数组

                   else

                            return new Object[0]; // 如非List类型则返回一个空数组

         }

         // 当TableViewer对象被关闭时触发执行此方法

         public void dispose() {}

         // 当TableViewer再次调用setInput()时触发执行此方法

         public void inputChanged(Viewer v, Object oldInput, Object newInput) {}

}

//-------------文件名:TableViewerLabelProvider.java-------------------

//标签器。如果说内容器是对输入表格的数据集作处理,那么标签器则是对数据集中的单个实体对象//进行处理和转化,由标签器来决定实体对象中的字段显示在表格的哪一列中

public class TableViewerLabelProvider implements ITableLabelProvider {

         //创建几个图像

         private Image[] images = new Image[] {

                            new Image(null, "icons/refresh.gif"),

                            new Image(null, "icons/star.jpg"),

                            new Image(null, "icons/moon.jpg") };

         // 由此方法决定数据记录在表格的每一列显示什么文字。 element参数是一个实体类对象

         // col是当前要设置的列的列号,0是第一列

         public String getColumnText(Object element, int col) {

                   PeopleEntity o = (PeopleEntity) element; // 类型转换

                   if (col == 0)// 第一列要显示什么数据

                            return o.getId().toString();

                   if (col == 1)

                            return o.getName();

                   if (col == 2)

                            return o.isSex() ? "男" : "女";

                   if (col == 3)

                            return String.valueOf(o.getAge()); // 将int型转为String型

                   if (col == 4)

                            return o.getCreateDate().toString();

                   return null; // 方法可以返回空值

         }

         // getColumnText方法用于显示文字,本方法用于显示图片

         public Image getColumnImage(Object element, int col) {

                   PeopleEntity o = (PeopleEntity) element;

                   // 只让“陈刚”这条记录显示图片

                   if (o.getName().equals("陈刚")||o.getName().equals("周阅")) {

                            if (col == 0)// 第一列要显示的图片

                                     return images[0];

                            if (col == 2)//根据性别显示不同的图标

                                     return o.isSex() ? images[1] : images[2];

                   }

                   return null; // 方法可以返回空值

         }

         // 当TableViewer对象被关闭时触发执行此方法

         public void dispose() {

                   //别忘了SWT组件的原则:自己创建,自释放

                   for (Image image : images) {

                            image.dispose();

                   }

         }

        

         // -------------以下方法很少使用,先不用管,让它们空实现-----------------

         public boolean isLabelProperty(Object element, String property) {return false;}

         public void addListener(ILabelProviderListener listener) {}

         public void removeListener(ILabelProviderListener listener) {}

}

程序说明:TableViewer的setInput方法的参数类型是Object,所以它可以接受任何类型的参数,因此在内容器中要将参数转换过来,如(List) element。但如果setInput不是List类型的参数,程序就会出错,所以最好用element instanceof List来作一下类型判断会比较稳妥,在SWT/JFace编程中很多BUG都出在这种地方。当然,本例的setInput参数定的就是List类型,不用instanceof判断直接类型转换也没什么问题。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论