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), ...
随机推荐
- Archlinux 安装配置指导 2015-05-24
因为用的Linode VPS的系统是Archlinux的,想在本地弄个系统做测试用,这样比较方便.然后发现自己在6年前做的一个Archlinux 安装配置Flash,好怀念的赶脚. 时过进迁,没想到A ...
- .Net平台-MVP模式初探(一)
为什么要写这篇文章 笔者当前正在负责研究所中一个项目,这个项目基于.NET平台,初步拟采用C/S部署体系,所以选择了Windows Forms作为其UI.经过几此迭代,我们发现了一个问题:虽然业务逻辑 ...
- Hibernate学习之检索策略
一.类级别的检索策略 类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索 –立即检索: 立即加载检索方法指定的对象 –延迟检索: 延迟加载检索方法指定的对象,在使用具体的属性时,再进行加载 ...
- Redis Sentinel的Redis集群(主从&Sharding)高可用方案
在不使用redis3.0之后版本的情况下,对于redis服务端一般是采用Sentinel哨兵模式,也就是一主多备的方式. 这里,先抛出三个问题, 问题1:单节点宕机数据丢失?问题2:多节点(节点间没有 ...
- MySQL varchar和char类型
varchar和char是两种最主要的字符串类型.不幸的是,很难精确地解释这些值是怎么储存在磁盘和内存中的,因为这根存储引擎的具体实现有关.下面的描述假设使用的存储引擎是InnoDB或者MyISAM. ...
- LineCalc,一个基于Lex&Yacc的简单行计算工具
LineCalc是基于Lex&Yacc的一个简单的行计算工具,支持常见的运算符和部分POSIX中定义于math.h中的数学函数:同时,LineCalc还提供了一个简单的错误处理模块,能检测公式 ...
- css3图片3D翻转效果
点击图片看翻转效果 html结构 <div class="flip"> <div class="front"> <img src= ...
- git配置ssh
$ git config --global user.name "yourname"$ git config --global user.email "youremail ...
- Acegi
https://blogs.oracle.com/darcy/entry/properties_via_annotation_processing http://www.oschina.net/que ...
- Android快速开发框架——AndroidAnnotations(Code Diet)
简介:AndroidAnnotations是一个依赖注入方式来简化代码结构 ,快速开发的开源框架,使结构代码更清晰,减少代码重复性.对今后我们做自动化测试和自动化埋点开发都会提高开发效率.跟我们之前使 ...