`

学习定制表格树的项(一)

 
阅读更多

原文:http://www.eclipse.org/articles/article.php?file=Article-CustomDrawingTableAndTreeItems/index.html

本来将原来那篇拷贝过来,想写一些注释的,但太大了,太慢了,还是另写吧:

  总述

1,为什么要定制去画呢?

因为原来的Item有自己的局限性: For example, an item in a table or tree can only contain one image, and it must appear before its text. Item的一个单元只能支持一个图像,而且只能默认画在字符串的前面。

 

2,在定制Item的时候,是基于Cell来画制的,什么是Cell,如果一个Table有2列3行,那么它就有6个Cell。

 

3,定制Item是由三个事件完成的,SWT.MeasureItem,SWT.EraseItem和SWT.PaintItem。

· SWT.MeasureItem: allows a client to specify the dimensions of a cell's content【长宽】

· SWT.EraseItem: allows a client to custom draw a cell's background and/or selection, and to influence whether the cell's foreground should be drawn【背景、选择时的处理、是否画默认的前景】

· SWT.PaintItem: allows a client to custom draw or augment a cell's foreground and/or focus rectangle【自己画或者增加前景】

 1, SWT.MeasureItem

1,SWT.MeasureItem是第一调用的用户定制事件。

2,SWT.MeasureItem中控制的content size而不是cell size,因为cell size包括了额外的装饰如checkboxes or tree indentation

SWT.MeasureItem事件预定的变量:

· item: the item

· index: the column index of item to be measured

· width: the default content width that the table would use if it were to draw the cell itself, based on its text, image, and checkbox

· height: the default content height that the table would use, based on the height of all of its items

· gc: a GC that is configured with the cell's font, which can be useful for performing string measurements

 

 3,例子

  

public class Snippet271 {

public static void main(String[] args) {

Display display = new Display();

Shell shell = new Shell(display);

shell.setBounds(10,10,150,150);

shell.setLayout(new FillLayout());

 

Table table = new Table(shell, SWT.NONE);

table.setLinesVisible(true);

for (int i = 0; i<3; i++) {

new TableItem(table, SWT.NONE).setText("item " + i);

}

table.addListener(SWT.MeasureItemnew Listener() {

public void handleEvent(Event event) {

event.height = event.gc.getFontMetrics().getHeight() * 2;

event.width *=  2;

}

});

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

display.dispose();

}

}

 


 

 

 

 程序中设置了Item的高度为gc字体高度的两倍,宽度为本来宽度的两倍。

  



 

这个是不改变Item高和宽的情况。

4,利用SWT.MeasureItem 改变Item的宽和高的有如下的限制:

a,现在宽和高时不可以缩小到比默认的小的,只能放大,不能缩小。

b,所有的Item在一个表格或一个Tree中,只有一个大小的高,增大一个,增大所有。

c,对于已经设置了宽度的column,SWT.MeasureItem 不起作用,在column调用Pack的时候,起作用。

例子:

 

public class Snippet272 {

public static void main(String[] args) {

Display display = new Display(); 

Shell shell = new Shell(display);

shell.setBounds(10,10,400,200);

Table table = new Table(shell, SWT.NONE);

table.setBounds(10,10,350,150);

table.setHeaderVisible(true);

table.setLinesVisible(true);

final TableColumn column0 = new TableColumn(table, SWT.NONE);

column0.setWidth(100); column0.setText("col1");

final TableColumn column1 = new TableColumn(table, SWT.NONE);

column1.setWidth(100); column1.setText("col2");

column0.addListener(SWT.Selectionnew Listener() {

public void handleEvent(Event event) {

column0.pack();

}

});

for (int i = 0; i < 5; i++) {

TableItem item = new TableItem(table, SWT.NONE);

item.setText(0, "item " + i + " col 0");

item.setText(1, "item " + i + " col 1");

}

table.addListener(SWT.MeasureItemnew Listener() {

public void handleEvent(Event event) {

event.width *= 2;

}

});

 

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

display.dispose();

}

}

 

 

 


 
  

col1只用在点击时调用column0.pack(),SWT.MeasureItem中定义的宽带加倍才起作用。

 

2SWT.EraseItem 

SWT.EraseItem是被调用的第二个事件,这个事件是在画背景前调用。背景包括背景和选择背景,这个事件允许用户画背景和选择背景。

该事件的预定义的变量:

· item: the item【事件的源】

· index: the column index of item being drawn

· xy: the table-relative co-ordinates of the top-left corner of the cell

· widthheight: the width and height of the full cellor the content width of the cell if the table has no columnsif these values were previously set by an SWT.MeasureItem listener then they are the same here 

· gc: the GC configured with the default foreground, background, font and clipping for the cell

detail: the logical OR of one or more of the following bits, indicating what will be drawn by default: 

 

· SWT.FOREGROUNDthis bit will be set if the default cell foreground will be drawn once the background has been drawn (default is true)我将这里理解为要不要完全由自己来画】

· SWT.BACKGROUND: this bit will be set if either a cell-specific or item-specific background color will be drawn for this cell (ie.- a color has previously been set with either TableItem.setBackground(Color) or TableItem.setBackground(int, Color))

· SWT.SELECTED: this bit will be set if the selection will be drawn for this cell, implying that this item is selected

· SWT.FOCUSED: this bit will be set if the focus rectangle will be drawn for this cell, implying that this item is the focus item in the table

· SWT.HOT(@since 3.3) this bit will be set if the mouse hover background will be drawn for this cell (not all platforms draw this)

 

doit: this boolean indicates whether the table will do the drawing specified in the detail field once this listener has completed (default is true)

 

 例子:

 

public class Example3 {

public static void main(String[] args) {

Display display = new Display(); 

Shell shell = new Shell(display);

final Color red = display.getSystemColor(SWT.COLOR_RED);

final Color yellow = display.getSystemColor(SWT.COLOR_YELLOW);

final Table table = new Table(shell, SWT.FULL_SELECTION);

table.setHeaderVisible(true);

new TableColumn(table, SWT.NONE).setWidth(100);

new TableColumn(table, SWT.NONE).setWidth(100);

new TableColumn(table, SWT.NONE).setWidth(100);

for (int i = 0; i < 5; i++) {

TableItem item = new TableItem(table, SWT.NONE);

item.setText(0, "item " + i + " col 0");

item.setText(1, "item " + i + " col 1");

item.setText(2, "item " + i + " col 2");

}

table.addListener(SWT.EraseItemnew Listener() {

public void handleEvent(Event event) {

event.detail &= ~SWT.HOT;

if ((event.detail & SWT.SELECTED) == 0) return/* item not selected */

int clientWidth = table.getClientArea().width;

GC gc = event.gc;

Color oldForeground = gc.getForeground();

Color oldBackground = gc.getBackground();

gc.setForeground(red);

gc.setBackground(yellow);

gc.fillGradientRectangle(event.x, event.y, event.width, event.heightfalse);

gc.setForeground(oldForeground);

gc.setBackground(oldBackground);

event.detail &= ~SWT.SELECTED;

}

});

 

table.pack();

shell.pack();

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

display.dispose();

}

}

 

 

 

 实现了选择的在Item中,画上一个渐变的背景色。

这里要注意:

a,不能用event.detail==SWT.SELECTED的方法来判断有没有被选择上,这里detail可能好多位有效。

b,处理完最好要取消SWT.SELECTED事件,event.detail &= ~SWT.SELECTED取消,要不然默认的处理SELECTED的事件还是要被调用。

c,这里的gc.fillGradientRectangle(0, event.y, clientWidth, event.height, false);坐标用的0和clientWidth,如果用gc.fillGradientRectangle(event.x, event.y, event.width, event.height, false);就成了下图的效果,想想就知道了,EraseItem事件是针对每一个cell,这样就是三个独立的cell画了三次,实际上上面也是画了三次,只不过都是重复了。




 
 

 

再一个画背景的例子:

 

public class Snippet273 {

public static void main(String[] args) {

final String[] MONTHS = {

"Jan""Feb""Mar""Apr""May""Jun",

"Jul""Aug""Sep""Oct""Nov""Dec"

};

final int[] HIGHS = {-7, -4, 1, 11, 18, 24, 26, 25, 20, 13, 5, -4};

final int[] LOWS = {-15, -13, -7, 1, 7, 13, 15, 14, 10, 4, -2, -11};

final int SCALE_MIN = -30; final int SCALE_MAX = 30;

final int SCALE_RANGE = Math.abs(SCALE_MIN - SCALE_MAX);

 

Display display = new Display();

Shell shell = new Shell(display);

shell.setBounds(10,10,400,350);

shell.setText("Ottawa Average Daily Temperature Ranges");

final Color blue = display.getSystemColor(SWT.COLOR_BLUE);

final Color white = display.getSystemColor(SWT.COLOR_WHITE);

final Color red = display.getSystemColor(SWT.COLOR_RED);

// final Image parliamentImage = new Image(display, "./parliament.jpg");

final Table table = new Table(shell, SWT.NONE);

table.setHeaderVisible(true);

table.setLinesVisible(true);

table.setBounds(10,10,350,300);

// table.setBackgroundImage(parliamentImage);

for (int i = 0; i < 12; i++) {

TableItem item = new TableItem(table, SWT.NONE);

item.setText(MONTHS[i] + " (" + LOWS[i] + "C..." + HIGHS[i] + "C)");

}

final int clientWidth = table.getClientArea().width;

 

table.addListener(SWT.MeasureItemnew Listener() {

public void handleEvent(Event event) {

int itemIndex = table.indexOf((TableItem)event.item);

int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth/SCALE_RANGE;

event.width = rightX;

}

});

table.addListener(SWT.EraseItemnew Listener() {

public void handleEvent(Event event) {

int itemIndex = table.indexOf((TableItem)event.item);

int leftX = (LOWS[itemIndex] - SCALE_MIN) * clientWidth/SCALE_RANGE;

int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth/SCALE_RANGE;

GC gc = event.gc;

Rectangle clipping = gc.getClipping();

clipping.x = leftX;

clipping.width = rightX - leftX;

gc.setClipping(clipping);

 

Color oldForeground = gc.getForeground();

Color oldBackground = gc.getBackground();

gc.setForeground(blue);

gc.setBackground(white);

gc.fillGradientRectangle(event.x, event.y, event.width/2, event.heightfalse);

gc.setForeground(white);

gc.setBackground(red);

gc.fillGradientRectangle(

event.x + event.width/2, event.y, event.width/2, event.heightfalse);

gc.setForeground(oldForeground);

gc.setBackground(oldBackground);

event.detail &= ~SWT.BACKGROUND;

event.detail &= ~SWT.HOT;

}

});

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

// parliamentImage.dispose();

display.dispose();

}

}

 




 
这个程序画了渥太华的12个月的温度情况,画的非常的逼真啊。

 画法就是每一列的长度为【(HIGHS[itemIndex] - SCALE_MIN) * clientWidth/SCALE_RANGE;】,画的时候把gc中设置一个clipping,这样就只有这个回形针区域可以画上去了。然后两段都是渐进第一段蓝色到白色渐进,第二段是白色到红色渐进,蓝色表示冷,红色表示热了。还是比较形象的。

 

 3SWT.PaintItem 

这个事件在默认的前景已经画好后,再调用。

这个事件的预定义的变量有:

· item: the item

· index: the column index of item being drawn

· xy: the table-relative co-ordinates of the top-left corner of the cell's content (ie.- its image or text)

· widthheight: the width and height of the cell's content; if these values were previously set by an SWT.MeasureItem listener then they are the same here

· gc: the GC configured with the default foreground, background, font and clipping for the cell

· detail: the logical OR of zero or more of the following bits: 

SWT.SELECTED: this bit will be set if the item is selected

SWT.FOCUSED: this bit will be set if the item is the table's focus item

SWT.HOT(@since 3.3) this bit will be set if the mouse hover background will be drawn for this cell (not all platforms draw this)

例子:

 

public class Snippet220 {

public static void main(String [] args) {

Display display = new Display();

Shell shell = new Shell(display);

shell.setBounds(10, 10, 350, 200);

Image xImage = new Image (display, 16, 16);

GC gc = new GC(xImage);

gc.setForeground(display.getSystemColor(SWT.COLOR_RED));

gc.drawLine(1, 1, 14, 14);

gc.drawLine(1, 14, 14, 1);

gc.drawOval(2, 2, 11, 11);

gc.dispose();

final int IMAGE_MARGIN = 2;

final Tree tree = new Tree(shell, SWT.CHECK);

tree.setBounds(10, 10, 300, 150);

TreeItem item = new TreeItem(tree, SWT.NONE);

item.setImage(xImage);

item.setText("root item");

for (int i = 0; i < 4; i++) {

TreeItem newItem = new TreeItem(item, SWT.NONE);

newItem.setText("descendent " + i);

if (i % 2 == 0) {

newItem.setData(xImage);

}

newItem.setImage(xImage);

item.setExpanded(true);

item = newItem;

}

 

tree.addListener(SWT.MeasureItemnew Listener() {

public void handleEvent(Event event) {

TreeItem item = (TreeItem)event.item;

Image trailingImage = (Image)item.getData();

if (trailingImage != null) {

event.width += trailingImage.getBounds().width + IMAGE_MARGIN;

}

}

});

tree.addListener(SWT.PaintItemnew Listener() {

public void handleEvent(Event event) {

TreeItem item = (TreeItem)event.item;

Image trailingImage = (Image)item.getData();

if (trailingImage != null) {

int x = event.x + event.width + IMAGE_MARGIN;

int itemHeight = tree.getItemHeight();

int imageHeight = trailingImage.getBounds().height;

int y = event.y + (itemHeight - imageHeight) / 2;

event.gc.drawImage(trailingImage, x, y);

}

}

});

 

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

xImage.dispose();

display.dispose();

}

}

 


 

 

 

在Item的后面,画图像。

可不可完全由我们来画,不好默认的呢?

下面例子:

 

public class Snippet231 {

public static void main(String [] args) {

final int COLUMN_COUNT = 4;

final int ITEM_COUNT = 8;

final int TEXT_MARGIN = 3;

Display display = new Display();

Shell shell = new Shell(display);

final Table table = new Table(shell, SWT.FULL_SELECTION);

table.setHeaderVisible(true);

table.setLinesVisible(true);

for (int i = 0; i < COLUMN_COUNT; i++) {

new TableColumn(table, SWT.NONE);

}

for (int i = 0; i < ITEM_COUNT; i++) {

TableItem item = new TableItem(table, SWT.NONE);

for (int j = 0; j < COLUMN_COUNT; j++) {

String string = "item " + i + " col " + j;

if ((i + j) % 3 == 1) {

string +="\nnew line1";

}

if ((i + j) % 3 == 2) {

string +="\nnew line1\nnew line2";

}

item.setText(j, string);

}

}

 

table.addListener(SWT.MeasureItemnew Listener() {

public void handleEvent(Event event) {

TableItem item = (TableItem)event.item;

String text = item.getText(event.index);

Point size = event.gc.textExtent(text);

event.width = size.x + 2 * TEXT_MARGIN;

event.height = Math.max(event.height, size.y + TEXT_MARGIN);

}

});

table.addListener(SWT.EraseItemnew Listener() {

public void handleEvent(Event event) {

event.detail &= ~SWT.FOREGROUND;

}

});

table.addListener(SWT.PaintItemnew Listener() {

public void handleEvent(Event event) {

TableItem item = (TableItem)event.item;

String text = item.getText(event.index);

/* center column 1 vertically */

int yOffset = 0;

if (event.index == 1) {

Point size = event.gc.textExtent(text);

yOffset = Math.max(0, (event.height - size.y) / 2);

}

event.gc.drawText(text, event.x + TEXT_MARGIN, event.y + yOffset, true);

}

});

 

for (int i = 0; i < COLUMN_COUNT; i++) {

table.getColumn(i).pack();

}

table.pack();

shell.pack();

shell.open();

while (!shell.isDisposed()) {

if (!display.readAndDispatch()) display.sleep();

}

display.dispose();

}

}

 

 



 
  

 表格中width取字符串宽加空白边框,height是字符串高加空白边框。这里的高和宽都是有GC计算的。

SWT.EraseItem事件取消的SWT.FOREGROUND事件,完全有我们自己去画了,画的时候用event.gc.drawText就行了。注意最后的column.pack()是必须的,前面没有设置column的宽度,调用pack才会计算column的宽度。

 

 文章看完了,比较的长,看几遍,有些问题还没有拓展。在网页上编辑,代码总是乱,没有办法只有在word编辑了再考上去了。

原文链接:http://www.eclipse.org/articles/article.php?file=Article-CustomDrawingTableAndTreeItems/index.html

 

  • 大小: 5.1 KB
  • 大小: 5.5 KB
  • 大小: 14.2 KB
  • 大小: 13.7 KB
  • 大小: 13.6 KB
  • 大小: 22.4 KB
  • 大小: 10.9 KB
  • 大小: 39.8 KB
分享到:
评论

相关推荐

    qt树型表格,并带有多行表头,超牛

    总之,“qt树型表格,并带有多行表头,超牛”这一项目充分展示了QT框架在GUI编程中的定制和扩展能力。它不仅为数据展示提供了一种高效且灵活的解决方案,也为QT社区的开发者们提供了一个宝贵的学习资源。通过学习和...

    VFP表格制作的树控件实例

    5. **美化和交互**:可以进一步定制表格的外观,如改变行高、列宽,添加图标以区分父节点和子节点,或者添加右键菜单以提供更多的操作选项。 6. **性能优化**:如果数据量较大,为了避免一次性加载所有数据导致的...

    Ztree+treeTable实现 Java实现 树形菜单 树形表格

    你需要定义一个`ul`元素作为树的容器,并在JavaScript中设置相应的配置项,例如节点的展开/关闭行为、节点点击事件等。同时,你需要为每个节点提供ID、父ID、名称等属性,形成JSON数据结构,供Ztree解析。 2. **...

    Ext下拉树、下拉表格

    导入项目后,确保正确引用了Ext库,并根据项目的具体需求调整和定制下拉树和下拉表格的配置。如果在开发过程中遇到问题,可以查阅Ext的官方文档,那里有详尽的API参考和示例代码。同时,利用浏览器的开发者工具进行...

    一个基于 vue 的 PC 端表格组件

    在Web应用开发中,表格组件是不可或缺的一部分,特别是在PC端的数据展示和管理中。本项目是一个基于Vue.js构建的PC端表格组件,名为“vxe-table”。这个组件具有丰富的功能,能满足各种复杂的业务需求。 首先,让...

    wpf实现DataGrid列表控件实现树形结构,并且展开控件ToggleButton可以放在任意一列,也可以冻住多列不可拖动

    在DataGrid中,我们可以定义一个HierarchicalDataTemplate来表示每一层的数据项,并设置其ItemsSource属性,使每一项都能展示其子项。 2. **ToggleButton**: 要在任意列放置展开/折叠按钮,我们可以自定义一个...

    Dhtmlx包,包含树,日历,菜单,表格等控件

    通过自定义图标、节点文本和行为,可以创建符合项目需求的定制化树形视图。 2. **日历控件(dhtmlxCalendar)**:提供一个用户友好的日期选择器,支持多种日期格式和日期范围选择。它可以与表单集成,方便用户输入...

    QT结构树界面设计,一级部门,二级部门,人员等

    `QTreeWidget`是一个可定制的控件,提供了一个表格样式的视图,而`QTreeView`则更灵活,通常与`QAbstractItemModel`一起使用,允许自定义数据模型。在这个项目中,一级部门可能被表示为树的顶层节点,二级部门作为一...

    WPF下的TreeTable实现示例

    在TreeView的每个项模板中,嵌入一个DataGrid,当点击TreeItem时,DataGrid会显示与该TreeItem关联的详细数据。 3. **数据绑定** WPF的强项在于数据绑定,TreeTable的实现同样依赖于数据绑定。你需要一个数据模型...

    使用jsTree实现js树形结构

    这里的 `data` 配置项定义了树的初始结构,每个对象代表一个节点,`text` 属性为节点文本,`children` 为子节点数组。 **二、jsTree 功能扩展** 1. **多态性** jsTree 支持多种数据源,如 JSON、HTML 或者 AJAX...

    ext2.0 树的增删改操作

    它提供了丰富的组件库,包括各种图表、表格、按钮、菜单、树形控件等。在这个项目中,我们主要关注的是"树的增删改操作"以及"下拉树"。 在Ext2.0中,树形控件(Tree)是一种非常实用的数据展示方式,常用于层级结构...

    三级树形+用户控件分配权限

    在这个场景中,我们关注的是一个基于“三级树形结构”和“用户控件(UserControl)”来实现动态生成父子菜单,并用于分配用户权限的系统。这样的设计可以提供灵活且直观的权限控制,使管理员能够有效地管理不同用户的...

    MFC树形列表和list列表简单例子

    列表控件可以显示一列或多列的数据,通常用于显示表格数据。CListCtrl提供了多种视图模式,如报告视图、小图标视图、大图标视图和详细信息视图。使用步骤如下: 1. 在资源编辑器中添加一个列表控件。 2. 声明...

    Ext4.2可增删树例子

    为了学习和使用这个例子,你可以打开Test文件查看代码,理解其工作原理,并根据自己的需求进行定制。 总结来说,Ext4.2可增删树例子通过扩展和优化Ext4.2的树组件,实现了节点leaf属性的动态调整,提升了树形结构在...

    EXTJS网页框架一个很好的实例动态

    2. 创建树形图配置:定义树形图的配置项,包括数据源、节点类型、渲染样式等。 3. 加载XML数据:使用EXTJS的Ajax接口或者Store组件从服务器获取XML数据,然后将数据解析并加载到树形图中。 4. 渲染树形图:在页面上...

    树表控件(带源码)

    标题中的“树表控件(带源码)”指的是一个结合了树形结构和表格数据展示的用户界面组件,通常用于软件开发中,特别是在Windows应用程序中。这种控件允许用户以树状结构组织数据,并在每个节点下显示表格形式的相关...

    js数据可视化 随机生成表格.zip

    使用D3.js,你可以精确控制每一个元素的位置和属性,从而实现高度定制化的图表。虽然学习曲线较陡峭,但其灵活性和强大的功能使其成为专业数据可视化项目的首选。 其次,ECharts是由百度开发的一个开源JavaScript...

    实现extjs4 的树、grid、form、query等大部分组件的功能

    例如,可以在树组件中选择一项,然后在关联的网格中显示其详细信息;或者通过表单收集用户输入,再用查询功能对数据进行筛选。在项目“bookSys”中,可能就是构建一个图书管理系统,用户可以通过树形结构浏览书籍...

    Qt Model/View Framework学习笔记

    Views 是显示数据的组件,它们负责将 model 中的数据以不同的形式显示出来,如列表、表格、树形结构等。Qt 提供了一些现成的 views,如 QListView、QTableView、QTreeView 等。 Delegates 是负责对数据项的渲染和...

    jquery-TreeTable树型结构 源码及示例

    2. **初始化表格**:使用`$("#tableId").treetable({options})`初始化你的表格,`options`是一个包含配置项的对象。 3. **标记父节点和子节点**:在HTML表格中,通过`data-parent`属性指定父节点,`data-id`属性标识...

Global site tag (gtag.js) - Google Analytics