在上一篇介绍了SWT/JFace窗口的建立,以及窗口的一些属性的设置。还有菜单栏的建立。下面介绍一下表格的建立。在SWT中有个Table类,用法也比较简单。但是我们一般采用的是JFace中的TableViewer来建立一个表格。我们可以从API文档中看到,SWT的Table和JFace的TableViewer并不是继承关系,他们属于两条不同的继承链。但是从TableViewer的源代码中可以发现,TableViewer把Table作为一个实例变量,也就是说TableViewer是对Table的一种扩展。关于数据传输类的建立这些就暂不做介绍了,我们直达正题,建立一个表格,并在其中显示出数据。建立TableViewer需要几个步骤,一般只要按照这个步骤来做Table,那就没什么大的问题了。
1、 建立TableViewer对象,定义Table的式样,和SWT中其他的式样用法是一样的。
2、 将TableViewer置于容器中,并对其布局,这个和其他SWT组件是一样的。
3、 创建TableViewer中的标题,就是Header
4、 设置内容器
5、 设置标签器
6、 用setInput方法将数据显示在表格中。
经过上面6步,表格就基本上建立完成了。这里要说明一下什么是内容器和标签器。Jface的TableViewer把写入数据封装成了2个接口,一个就是内容器接口IStructuredContentProvider,还有个就是标签器接口ITableLabelProvider。我们需要实现这两个接口的两个方法才能将数据写入到表格中。内容器是接收到1个Object对象,这个Object对象可以是容器类对象或者数组,然后返回一个一维Object数组。他的作用就是通过传递进来的参数来自动设置表格中的数据需要占多少行。标签器接口中的getColumnText方法参数是1个object对象和需要写入数据的列数,返回一个String对象。他的作用相当于把每个字段的值写入到表格中。当我们实现了这些方法后,这些方法该如何调用是不需要我们关心的,你只要保证传进来的参数不会出现问题那就行了。我们只需要在程序中创建这两个类的对象,然后将他们作为TableViewer的setContentProvider()和setLabelProvider()这两个方法的参数就行了,最后将要放入表格的集合类对象或者数组作为setInput()的参数,表格的数据显示就完成了。
SWT中的布局管理器我这里就不多讲了,有兴趣可以翻翻这方面的资料,比较的常用的还是GridLayout和FormLayout,这两个布局管理器是SWT中最复杂也是最强大的两个布局管理器,无论你是选择这两种中的哪一种,完全可以设计出任何复杂的界面。GridLayout是按行和列来排列组件的,他主要是用在窗体大小固定不变的时候,如果窗体大小会发生变化,那使用这个布局管理器就显得有点力不从心了。我还是比较倾向于使用FormLayout,因为这个管理器是按位置的百分比来设置组件的位置,也可以相对于某个组件来排列,用它来管理布局界面,可以让我们的界面排列方式更加细致。尽管他使用起来还要复杂点。下面将演示如何建立表格,并通过相应的按钮向里面一行一行的添加数据。还可以对表格的所有数据进行清空以及显示。双击表格中的数据时会弹出窗口显示当前选中行的第0列字段的值。在大多数例子中都只演示了如何通过集合类,如List,Set,Map等将数据写入到表格中,我这里演示一下如将二维数组写入表格中。
将下面的代码替换上篇文章中主窗口类的createContents方法,下面还有个监听器的方法,写在这个方法的下面也可以
protected Control createContents(Composite pare) { // 获得窗口的shell对象 Shell shell = this.getShell(); Toolkit kit = Toolkit.getDefaultToolkit(); // 设置窗口标题 shell.setText("我的通讯录-授权:Administrator"); // 设置窗口默认大小 shell.setSize(700, 400); // 将窗口居中 shell.setLocation((kit.getScreenSize().width - 700) / 2, (kit .getScreenSize().height - 400) / 2); MenuManager popMenu = new MenuManager(); popMenu.add(new OpenFile()); popMenu.add(new SaveFile()); Menu menu = popMenu.createContextMenu(pare); pare.setMenu(menu); //创建FormLayout布局管理器对象 FormLayout form = new FormLayout(); //将pare容器按照FormLayout来布局 pare.setLayout(form); //通过JFaceTable类的creatTableViewer()创建一个TableViewer对象 final TableViewer tableViewer = new JFaceTable().creatTableViewer(pare); //设置TableViewer内容器 tableViewer.setContentProvider(new JFaceTable().new TableViewerContentProvider()); //设置TableViewer标签器 tableViewer.setLabelProvider(new JFaceTable().new TableViewerLabelProvider()); //增加表格中双击事件,可以获得当前选择行的第一列字段的值。 tableViewer.addDoubleClickListener(new IDoubleClickListener(){ public void doubleClick(DoubleClickEvent e) { TableItem item = tableViewer.getTable().getItem(tableViewer.getTable().getSelectionIndex()); MessageDialog.openInformation(null,"提示",item.getText(0)); } }); //创建FormLayout布局管理器的布局数据类对象 FormData formData = new FormData(); //FormAttachment是FormData更进一步的布局数据类 //该组件左边距他父容器左边距离的百分比。第二个参数是偏移量 formData.left = new FormAttachment(0, 5); //该组件右边距他父容器左边距离的百分比 //这里设置的时候左边一定要比右边的百分比小,否则组件就会看不见了。 formData.right = new FormAttachment(100, -5); //该组件上边距他父容器上面距离的百分比 formData.top = new FormAttachment(0, 5); //该组件下边距他父容器上面距离的百分比 //这里设置的时候上边一定要比下边的百分比小,否则组件就会看不见了。 formData.bottom = new FormAttachment(100, -80); //获得tableViewer的Table对象 //因为在TableViewer里面包含有Table,所以我们依然可以在TableViewer //上使用Table类的方法,不过要先获得该TableViewer对象的table对象 Table table = tableViewer.getTable(); //将这个布局数据类应用于table table.setLayoutData(formData); //建立一个带有标题文字和边框的容器 Group group = new Group(pare, SWT.NONE); group.setText("控制区"); formData = new FormData(); formData.left = new FormAttachment(0, 5); formData.right = new FormAttachment(100, -5); formData.top = new FormAttachment(table, 5, SWT.BOTTOM); formData.bottom = new FormAttachment(100, -5); group.setLayoutData(formData); GridLayout grid = new GridLayout(); grid.numColumns = 2; group.setLayout(grid); Button button_1 = new Button(group, SWT.NONE); button_1.setText(" 增加 "); GridData gridData = new GridData(); gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = GridData.CENTER; button_1.setLayoutData(gridData); //建立按钮的事件监听器 button_1.addSelectionListener(new Selection(tableViewer, button_1)); Button button_2 = new Button(group, SWT.NONE); button_2.setText(" 清空 "); gridData = new GridData(); gridData.grabExcessHorizontalSpace = true; gridData.horizontalAlignment = GridData.CENTER; button_2.setLayoutData(gridData); button_2.addSelectionListener(new Selection(tableViewer, button_2)); // . // . // . return pare; } private class Selection extends SelectionAdapter { private TableViewer tv; private Object button; public Selection(TableViewer tv, Object button) { this.tv = tv; this.button = button; } public void widgetSelected(SelectionEvent e) { String str = ((Button) e.getSource()).getText(); if (str.equals(" 增加 ")) { Object[][] object = new Object[1][4]; for (int i = 0, j = index + 1; i < object[0].length; i++) object[0][i] = Integer.toString(j); /* tableViwer的添加行的方法,这个方法可以将数据 * 添加到表格中,并且不会影响到表格中其他的数据, * 而如果使用setInput会把以前在表格中的数据全部替换掉, * 当然如果你再使用getInput(),那么只能获得以前使用 * setInput时添加的数据,而后面使用add方法添加的数据 * 是不会被获得的。*/ tv.add(object); index++; } if (str.equals(" 清空 ")) { if (tv.getTable().getItemCount() != 0) { index = tv.getTable().getItemCount(); /* removeAll()是Table的方法,将当前表格中 * 所有的数据全部清空*/ tv.getTable().removeAll(); ((Button) button).setText(" 显示 "); } } if (str.equals(" 显示 ")) { Object[][] object = new Object[index][4]; for (int i = 0; i < object.length; i++) { for (int j = 0; j < 4; j++) { object[i][j] = i + 1; } } tv.setInput(object); ((Button) button).setText(" 清空 "); } } }
/****************文件名:JFaceTable.java****************/
public class JFaceTable { /* 用于实现IStructuredContentProvider接口,此接口一般都只 * 用实现getElements()这个方法,其他的方法为空就行了*/ class TableViewerContentProvider implements IStructuredContentProvider{ /* 这里的参数就是我们使用setInput()传进的参数,因为我使用的是数组 * 所以接受的参数也是二维数组。 */ public Object [] getElements(Object element) { //因为该方法不能返回null,所以要先判断一下数据的正确性,否则会 //报异常。 if (element instanceof Object []) { //首先将此参数转换成一维数组 return (Object []) element; } else { return new Object [0]; } } /* 下面的方法可以设置为空*/ public void dispose() {} public void inputChanged(Viewer arg0, Object arg1, Object arg2) {} } /* 用于实现ITableLabelProvider接口,此接口一般都只 * 用实现getElements()这个方法,其他的方法为空就行了*/ class TableViewerLabelProvider implements ITableLabelProvider{ /* 这里的element参数,其实就是我们二维数组中的每一个一维数组,其中保存的是 * 每一行的所有数据,通过column这个参数依次写入到表格中的各个字段上。 * column具体值是多少我们并不知道,因此需要我们来判断,并根据他里面的值 * 来决定我们要将哪个数据返回。同样,该方法是不能返回NULL的。必须先检查数 * 有效性。*/ public String getColumnText(Object element, int column) { if (element instanceof Object []) { for (int i = 0; i < ((Object []) element).length; i++) { if (column == i) { return ((Object []) element)[column].toString(); } } } return ""; } public Image getColumnImage(Object arg0, int arg1) { return null; } public void addListener(ILabelProviderListener arg0) {} public void dispose() {} public boolean isLabelProperty(Object arg0, String arg1) { return false; } public void removeListener(ILabelProviderListener arg0) {} } /* 下面的方法就是用于创建TableViewer对象的,并返回给主窗口*/ public TableViewer creatTableViewer(Composite pare){ //创建TableViewer对象,这里有几个式样。BORDER:有边框|MULTI:可以多选 //FULL_SELECTION整行选择。 TableViewer tableViewer = new TableViewer(pare,SWT.BORDER|SWT.MULTI|SWT.FULL_SELECTION); //获得TableViewer的table对象,并在后面设置他的表头是否显示, //是否具有表格线。 Table table = tableViewer.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); //设置table的专有表格布局管理器。 TableLayout tableLayout = new TableLayout(); table.setLayout(tableLayout); //下面都是设置表头上的文字和每一列表格占的比例宽。 tableLayout.addColumnData(new ColumnWeightData(10)); new TableColumn(table,SWT.NONE).setText("序号"); tableLayout.addColumnData(new ColumnWeightData(10)); new TableColumn(table,SWT.NONE).setText("姓名"); tableLayout.addColumnData(new ColumnWeightData(10)); new TableColumn(table,SWT.NONE).setText("性别"); tableLayout.addColumnData(new ColumnWeightData(10)); new TableColumn(table,SWT.NONE).setText("年龄"); return tableViewer; } }