QTableView另类打印解决方案(复用render函数去解决print问题)
Qt QTableView另类打印解决方案
上回书说道Qt的model/view,我就做了个demo用于显示数据库中的内容。没想到tableview的打印竟然成了问题。我困惑了,难道Qt不应该提供一个print函数给tableview吗?这是最最常用的功能啊。
Google了半天,也没什么有用的结果。看到Qt labs有一篇blog,叫“All You Need is a little Polish”,里面给出了最新的spreadsheet demo中的tableview print代码。还挺高兴,原来已经可以解决了。后来试了一下,发现根本不是那么回事,这个例子只能打印tableview当前显示的区域,对于分页、页眉、页脚、等等都不支持。原来写这个demo的并不是真正的开发人员,只是support team的。
作为10年的老MFCer,我有着厚脸皮的DIY精神(没办法,被逼的太多次了,每次只能自己来)。相信以我在MFC中写Doc/View printing的经验,搞定Qt的打印还是没问题的。但是在跳进代码海之前,我花了几个小时仔细研究了一下QTableView的代码,发现我可以选下面几个实现方案。
1. 鸵鸟方案
学过操作系统的Tx都知道这意味着什么样的方案。上面提的那篇Blog里的方法可以算一种喽。如果你打印的table每次都是在1页内的话,可以用这个方案。但是作为10年英明神武的老MFCer,实在没脸这样做。
2. model方案
这个方案是从model中取得所有table的数据,然后使用2个for循环将这些数据以行和列打印出来。在qt-app网站上有人给出了这个解决方案(http://qt-apps.org/content/show.php/TableView+Printer?content=76616)。我看了代码,作者在打印每页时从model中取数据,然后在内存中生成一个graphicview,然后用graphicview打印。也实现分页等功能。但打印的效果不好,增加的边框感觉也很别扭。
还有人建议将model中的数据导入至QTextDocument中,然后利用QTextDocument稍微强大一点打印功能打印。
总之,所有这些方案实现起来比较麻烦,而且只从model中取数据,忽略了view(delegate)中显示相关的因素(如文字render的格式,是否被选中等等)。还有一点就是分页总是成问题。即使纵向分页对了,横向的分页还是没看到相应的实现。(大家都注意到在Excel中一页横向打不下时会将未打印的内容打印至下一页吧)
3. delegate方案
在QTableView代码中,真正render每个item时,还是使用delegate的。所以有人建议使用delegate在2个for循环中将这些数据以行和列打印出来。这个貌似是最好的解决方案了。如果我是Qt开发人员的话,我会首选这个方案的。
4. 我的方案
可惜我不是Qt的开发人员(不知Nokia这种企业氛围如何)。个人感觉Qt的风格是沉稳,外加一丝灵动。所以我的方案可能不是Qt开发人员喜欢的。即使我个人也觉得这个方案难登大雅之堂。只是在时间和精力都有限的情况下,借助了Qt的一点Q,想出来的一个非常tricky的办法。
其实我的方案就是:鸵鸟方案的升级版。当当当。。。
我的灵感来源于上面Bolg中鸵鸟方案的4句代码:
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
resize(printer->width(), printer->height());
render(printer);
前面2具隐藏scrollbars,第3句,让view与print的纸张大小相同,最关键的第4句,直接将view render到printer中。
作为一个10年的老MFCer,我坚信Qt在代码复用性方面应该更胜一筹。既然view可以直接render到printer中(感谢Qt中painter和printer的设计),那么为什么还需要去写delegate的paint呢?所以,我的方案出发点就是从怎么复用render函数去解决print问题。
方案成功了吗?心急的Tx请先看下面的图片。
打印预览、横向分页、纵向分页、背景色、选中标记、页眉、页脚。。。。。。该有的都有了。从单页到上百页我都测试过。那么我的鸵鸟升级方案是怎么实现的呢?
其实非常简单,还是基于view的render函数,既然view当前显示的内容可以直接render到printer中,那么我就模拟给它翻页,然后render每页不就行了。最初的办法是使用QScrollBar的setValue对横向和纵向进行翻页。就是打完第1页之后,翻到第2页,再打印,以此类推。但最后一页很难处理,如果最后一页的内容只有几行的话,是没法继续向下翻得,造成的结果就是倒数第2页很多打印过的行会再次被打印出来。难道没办法了。
一筹莫展之际,只能继续翻Qt的文档,当看到tableview中setRowHidden和setColumnHidden这2个函数时,我一刹那被Carmack大仙(我的偶像)灵魂附体。这不就解决了吗?
什么?你还不明白?
打印完第1页时,将这页打印过的row隐藏,然后打印下一页。打印完纵向分页后,将横向打印过的colum隐藏。再次打印纵向分页(从而实现横向分页)。
剩下的就是数学了。。。
大部分问题都解决了。我写了个QTableView的派生类MyTableView,里面一些打印相关的代码用到了David Johnson david@usermode.org的textprinter中某些代码,感谢开源社区。我的MyTableView类可以实现下面的功能:
1. WYSIWYG打印/打印预览,这意味着每个item的背景颜色、文字颜色、显示属性、选择状态、边框、表头。。。。。。所有你看到tableview显示的,都可以原封不动直接打印出来;
2. 纵向分页,当在一页末尾某行没打印全时,会自动在下一页再次打印;
3. 横向分页,当在一页右侧某列没打印全时,会自动在下一次横向分页时再次打印;
4. 打印页眉
5. 打印页脚
6. 打印边距
7. 打印成PDF文件
http://blog.csdn.net/superjoel/article/details/5177199
QTableView另类打印解决方案(复用render函数去解决print问题)的更多相关文章
- render函数的使用
render函数的几种使用方法最近使用element-ui的tree组件时,需要在组件树的右边自定义一些图标,就想到了用render函数去渲染. <el-tree class="p-t ...
- javascript中的函数节流和函数去抖
带着问题去尝试 首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析! 1.比如搜索框,你会用到什么事件(change.blur.keyup等)?去做什么效果?2.再比如scro ...
- vue入门:(底层渲染实现render函数、实例生命周期)
vue实例渲染的底层实现 vue实例生命周期 一.vue实例渲染的底层实现 1.1实例挂载 在vue中实例挂载有两种方法:第一种在实例化vue时以el属性实现,第二种是通过vue.$mount()方法 ...
- JavaScript 函数节流和函数去抖应用场景辨析
概述 也是好久没更新 源码解读,看着房价蹭蹭暴涨,心里也是五味杂陈,对未来充满恐惧和迷茫 ...(敢问一句你们上岸了吗) 言归正传,今天要介绍的是 underscore 中两个重要的方法,函数节流和函 ...
- Vue.js之render函数基础
刚才翻了一下博客,才发现,距离自己写的第一篇Vue的博客vue.js之绑定class和style(2016-10-30)已经过去一年零两天.这一年里,自己从船厂的普通技术员,成为了一个微型不靠谱创业公 ...
- Vuejs2.0学习(Render函数,createElement,vm.$slots)
直接来到进阶部分, Render函数 直接来到Render,本来也想跳过,发现后面的路由貌似跟它还有点关联.先来看看Render 1.1 官网一开始就看的挺懵的,不知道讲的是啥,动手试了一下,一开头讲 ...
- JavaScript函数节流(throttle)与函数去抖(debounce)
对于浏览器窗口大小改变的时候,来动态改变页面元素的大小,可以采用window的resize事件,实现代码: <script type="text/javascript"> ...
- 【转】【Html】Vuejs2.0学习之二(Render函数,createElement,vm.$slots,函数化组件,模板编译,JSX)
1.Render函数 所以直接来到Render,本来也想跳过,发现后面的路由貌似跟它还有点关联.先来看看Render 1.1 官网一开始就看的挺懵的,不知道讲的是啥,动手试了一下,一开头讲的是Rend ...
- vue render函数 函数组件化
之前创建的锚点标题组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法,它只是一个接受参数的函数 在这个例子中,我们标记组件为functional,这意味它是无状态(没有data), ...
随机推荐
- samba服务器的安装及配置
安装前首先查看服务器是否已经安装samba服务器 [root@bogon home]# rpm -qa|grep samba system-config-samba-docs-1.0.9-1.el6. ...
- android 监听 USB 拔插广播消息
USBBroadcastReceiver.java package com.example.communication; import android.content.BroadcastReceive ...
- iOS keyChain(钥匙串)的简单使用
通常在开发中我们需要长久的保存某些值比如用户的账号密码等,对于隐私度很高的数据来说保证数据的安全性是尤为重要的.ios中的keyChain是一种很好的选择. 首先去开发者网站(https://deve ...
- Java随机输出验证码包含数字、字母、汉字
//随机验证码,有数字.字符 //生成随机数,然后再截取,还要限定随机数的范围 String zimu = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn ...
- 几个SQL
select sum(`value`) from testtable where value != 'error' AND type ='b' in (select DISTINCT(type) fr ...
- Unity5UGUI 官方教程学习笔记(二)Rect Transform
Rect Transform Posx Posy Posz : ui相对于父级的位置 Anchors :锚点 定义了与父体之间的位置关系 一个锚点由四个锚组成 四个锚分别代表了 ...
- 基于HTTP协议下载文件的实现
最近在开发文件下载的程序,该程序是基于HTTP开发的. 首先是了解了文件传输到客户端的大概格式,然后分析该格式,实现写入文件的功能. 自己构造的HTTP包如下: GET /*********.rar ...
- virtualBox文件共享
具体过程,可以参考: http://jingyan.baidu.com/article/2fb0ba40541a5900f2ec5f07.html 共享命令:sudo mount -t vboxsf ...
- svn和ftp的区别
svn和ftp的区别是: ftp修该文件后就会替换原来的内容无法恢复.如果要回复,还需要自己在替换前做备份.如果遇到多人同时操作同一文件就会很头疼.且无法对相应修改进行记录. svn可以将你每一次的修 ...
- android双击返回键退出程序
今天给大家简单说一下,android双击返回键退出程序. @Override public boolean onKeyDown(int keyCode, KeyEvent event) { ...