用QT的model/view/delegate接口实现自定义的窗口渲染

来源:互联网 发布:抑郁症是什么感觉 知乎 编辑:程序博客网 时间:2024/05/21 21:47

qt的model接口(qabstractItemModel)管理的数据抽象来说是节点树,最顶层的根节点可以有N行M列个子item,而每个item又可以有自己的N行M列个子item。


qt的view接口(qabstractItemView)的实现是从model获取数据,但要怎样在窗口中渲染这些数据,每个view的实例都可以有自己的实现,甚至可以忽略model中的部分item,仅渲染一部分感兴趣的item,渲染的图形可以是表状的,可以是圆饼型的,任何类型的渲染方式都可以,甚至什么都不渲染都行。


这完全取决于view在其paintEvent函数中的实现。paintEvent函数主要做两件事情,一,从model中读时间,二,渲染任意想要的图形。渲染即可以交给view对应的item delegate来实现,也可以view自己在paintEvent函数中直接渲染而不委托给delegate对象。


item delegate对象会实现paint函数,paint函数一次渲染一个item,所以在view的paintEvent函数中可以针对每个要渲染的item调用一次paint函数,paint函数的参数中指定了要渲染哪个item,然后是这个item要渲染的位置(用rect表示)。每个view有一个默认的item delegate,有默认的paint函数的实现。但是如果想要自定义的实现,就需要提供自定义的item delegate实例并实现paint函数。在paint函数中可以用画笔qpainter或者qt提供的其它函数去实现渲染。


view委托给delegate对象的好处是,view的实现一旦写好,如果想要修改对item的渲染方式,可以通过新实现的一个delegate类即可,好处是无需改变view的实现。所以qt预提供的tableView,treeView很成功,因为往往程序员可以直接用它们,程序员最多仅需要自己实现一个自定义的delegate类。但这种方式局限的地方在于delegate对item的渲染的区域取决于view给定的rect。所以如果想要彻底改变对item的渲染,可能就需要重新实现一个新的view,而不能简单通过添加一个delegate来实现了。


实践分析,怎样在view中渲染出下面的图形。




第一,如何渲染左边的圆饼??? 这些是完全在view的paintEvent函数中通过qpainter实现的。首先说明一下model中数据的结构,model有两列N行,第一列的item中的数据记录的是每一个元素的颜色和名字,第二列的item中的数据记录的是每一个元素的大小。


view的paintEvent函数先从model中获取第二列的所有的item的value,根据value的大小可以计算出每个元素在圆饼中的比例,而且还要从model中的第一列获取每个item的颜色,并且还要用QPainter去渲染一个个pie图形,pie的大小就是前面计算的比例,pie的颜色就是前面获取的颜色。


第二,如何渲染右边的图形?view决定让delegate对象去渲染,让delegate对象自己去读每个item的数据并决定如何渲染。但paintEvent函数中先计算要渲染的item的rect,然后将这个item(这个item中的数据包括了颜色和名字)连同rect(rect是放在style option对象里)一起作为参数调用一次item delegate的paint函数,默认的delegate就能实现图中的效果。


源代码可以参考qt的例子程序中的chart工程。


欢迎提出意见,因为本就是为交流而分享。下一次,我计划写下在上面的例子中是如何实现鼠标点击圆饼中的某部分导致model中第二列对应的一个model item被qt的selectionModel置为选中状态的。

0 0
原创粉丝点击