【转贴】-- 基于QT的跨平台应用开发
原帖地址:http://www.cnblogs.com/R0b1n/p/4106613.html
1 Qt简介
Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能。Qt很容易扩展,并且允许真正地组件编程。基本上,Qt 同 X Window 上的 Motif,Openwin,GTK 等图形界 面库和 Windows 平台上的 MFC,OWL,VCL,ATL 是同类型的东西。
2008年,奇趣科技被诺基亚公司收购,QT也因此成为诺基亚旗下的编程语言工具。2012年,Qt被Digia收购。2014年4月,跨平台集成开发环境Qt Creator 3.1.0正式发布,实现了对于iOS的完全支持,新增WinRT、Beautifier等插件,废弃了无Python接口的GDB调试支持,集成了基于Clang的C/C++代码模块,并对Android支持做出了调整,至此实现了全面支持iOS、Android、WP。(百度百科)
Qt作为高质量的跨平台框架,具有支持平台广泛、功能完整、开源、执行效率高、界面开发简单、开发工具完备等特性。下表是Qt与目前较为流行的跨平台解决方案Java和Xamarin比较结果。
Qt | Java | Xamarin | |
支持的桌面平台 |
Windows、Mac、Linux、 Unix、Solaris |
Windows、Mac、Linux、Unix、Solaris |
Windows、Mac、Linux |
支持的移动平台 |
Android、iOS、Window Phone |
Android |
Android、iOS、Window Phone |
开发语言 |
C++ | Java | C# |
是否开源 |
有开源版本(基于LGPL)也有商业版本 |
OpenJDK开源 |
只有商业版本,基于Mono框架为开源 |
开发工具 |
Qt Creator, Qt Designer |
Eclipse、NetBeans |
Monodevelop、Virtual Studio |
功能完成性 |
功能十分完整 |
功能十分完整 |
功能不十分完整 |
界面开发难度 |
简单 |
较复杂 |
较简单 |
成熟度 |
十分成熟 |
十分成熟 | 不十分成熟 |
目前最高版本 |
5.2 | 8.0 | 4.1 |
执行效率 |
相当好 | 较差 | 一般 |
依托公司 |
Digia.com (之前为Nokia) |
Oracle.com (之前是SUN) |
Xamarin.com |
几种跨平台框架的比较
Qt不但拥有了完善的C++图形库,而且近年来的版本逐渐集成了数据库、OpenGL库、多媒体库、网络、脚本库、XML库、WebKit库等组件,其核心库也加入了进程间通信、多线程等模块,极大的丰富了Qt开发大规模复杂跨平台应用程序的能力.Qt的开发工具Qt Creator(IDE)、GUI Designer(界面设计)、Build Tools(编译)、Help System(帮助系统)I18n Tools(多语言工具)等,也极大简化了开发应用的难度。下图为Qt的技术堆栈
2 Qt 编程关键技术
2.1 信号与槽
信号和槽机制是QT的核心机制,是一种高级接口,应用于对象之间的通信。信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler)的Qt工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码。
所有从QObject或其子类(例如QWidget)派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。对象甚至并不了解具体的通信机制。
信号与槽连接是任意个的,甚至信号与信号也可以连接的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。总之,信号与槽构造了一个强大的部件编程机制。
2.2 Qt事件处理
Qt可以说是是以事件驱动的UI工具集,信号与槽在多线程的实现也依赖于Qt的事件处理机制。在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent。Qt中事件的产生、分发、接受和处理:
(1)事件的产生如按键,点击鼠标等等动作所产生的keyPressEvent, keyReleaseEvent,mousePressEvent,mouseReleaseEvent等事件(分别被封装成QMouseEvent和QKeyEvent中),这些事件来自于底层的操作系统,它们以异步的形式通知Qt事件处理系统。
(2)事件的接受和处理使用QObject。事件处理机制是QObject三大职责(内存管理、内省与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
(3)事件的分发:对于non-GUI的Qt程序,是由QCoreApplication负责将QEvent分发给QObject的子类-Receiver。对于Qt GUI程序,由QApplication来负责。
3 Qt开发与实例分析
下面通过一个指标计算的程序分析Qt开发完整过程。该系统需求:
(2)从数据库中读取计算指标参数。(数据库操作组件)
(3)计算所的指标需要用温度计的形式展示,并截图以便在文档中使用。
(图像显示,截图)
(4)能够将计算数据通过Excel导入到数据库中,并能够将计算结果导出到Excel中。
(Excel操作组件)
(5)需要有Windows和Mac两个版本且功能和界面布局要基本相同。(跨平台)
3.1 开发环境
下表为使用的开发环境,基本为开源软件
系统平台 | Mac OSX 10.9 |
使用框架,SDK | Qt 5.2 ;SDK:qt-mac-opensource-5.2.1 |
开发工具 | Qt Creator 3.0;Qt Designer 3.0 |
开发语言 | C++,SQL |
数据库 | SQLite 3 |
测试平台 | Mac OSX;Window XP x86;Window 7 x86/x64 |
其他开源软件 |
FireFox SQLite Manager(管理数据库); Inno Setup Compiler(打包应用程序);VirtualBox(测试应用程序); yEd (绘制示意图) 其他库文件: QtXlsx (用于进行Excel操作) |
3.2 系统实现基本框架
该系统综合使用了Qt的数据库模块、GUI模块和第三方的QtXlsx模块,使用VirtualBox完成系统打包和测试,使用Inno setup对Windows程序进行封装,使用SQLite Manager管理SQLite数据库。下图为系统实现基本框架。
系统实现基本框架
3.3 数据库管理
Qt对数据的支持相当完善,Oracle、SQL Server、DB2、 SyBase、 MySQL、 PostgreSQL、 SQLite3 都可以完美的支持。由于需求要使用本地数据库并尽可能的小巧灵活,选择SQLite3作为数据库,通过FireFox 插件SQLite Manager进行管理,图4为SQLite Manager 管理界面。Qt使用QsqlDatabase类来管理数据,该类中包括所有数据库的管理行为,如addDatabase为添加数据库驱动,下面为连接SQLite3示例代码。
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); if (!QSqlDatabase::drivers().contains("QSQLITE")) QMessageBox::critical(0, QObject::tr("Unable to load database"), QObject::tr("This demo needs the SQLITE driver")); db.setDatabaseName (dbName); if (!db.open()) { QMessageBox::critical (0,QObject::tr ("DataBase Error"),db.lastError ().text ()); return false; }
数据库连接代码
对于已经连接上的数据库可以使用两种方法来进行操作:
(1)使用QSqlQuerry,该方法可以直接执行SQL语句,使用与对数据库的批量处理。如:
“query.exec ("DROP VIEW IF EXISTS 'data_x300';");”
(2)使用QSqlTable,将数据库中的表转换为Qt中的Table,然后进行数据库增添删改等事务性操作,简单而且安全,推荐使用这种方法操作代码。下面为使用QSqlTable代码
if((model->insertRow (row))&& (model->setData(model->index(row,0),id))&& (model->setData(model->index(row,1),name))&& (model->setData(model->index(row,2),newPasswd))&& (model->setData(model->index(row,3),hint))&& (model->submitAll())) QMessageBox::warning (this, "Correct","用户添加成功!"); else QMessageBox::warning (this, "Error","密码添加失败!");
3.4 Qt中界面设计
Qt使用Qt Designer Form,该方法直观且功能强大。首先使用Qt Designer建立并绘制以xxx.ui为后缀的文件,然后在编译时会将其转换为ui_xxx.h头文件,再进行统一的编译。图6为Qt Designer界面。在Qt5加入了对基于JS的QML进行界面的支持,QML觉Qt Designer Form有更强的控制能力和美化能力,而且使用目前流行的JS语言,相信必将成为未来发展趋势。
该系统中还要求用温度计显示计算结果,因此单单是界面绘制工具并不能满足要求。需要先找到温度计的样本图,使用绘图工具进行修改,最后使用Style Sheet脚本对控件进行美化处理。下图为StyleSheet处理脚本和效果。
Style Sheet处理脚本及效果
该系统需要对结果截屏,Qt中截屏又两种方式,一种方式是在整个屏幕中,根据相对位置进行截屏(pixmap.grabWindow());另外一种是在Qt中的一个窗口中(pixmap.grabWidget()),根据相对位置进行截屏。下面为截屏代码:
int grapX= year_lineEdit->geometry ().x ();
int grapY = year_lineEdit->geometry ().y ();
pix = pixmap.grabWidget (this, grapX-2 ,grapY -2, this->width ()-grapX, this->height ()-grapY -140);
3.5 对Excel进行操作
该系统将需用Excel将计算数据导入到数据库中,并将计算结果导出到Excel中。但在Qt中并没有对Office进行处理的组件,因此需要第三方组件进行支援。我们使用开源的Qt模块QtXlsx该模块可以对Excel进行操作,功能十分强大。(Qt更多开源模块可以在http://inqlude.org 上找到。)使用方法如下:
(1) 首先在网站上下载QtXlsx模块项目,安装Perl5,使用Qt Creator打开并编译;
(2) 然后再命令行中使用“qmake; make; make install”来安装库
(3) 在pro文件中加入xlsx模块,在头文件中加入"xlsxdocument.h"头文件
即可以使用QtXlsx库进行Excel操作了,下面为QtXlsx操作代码:
QString fileName = path + "/index.xlsx"; QXlsx::Document *xlsx = new QXlsx::Document(fileName); int rowC = (model->rowCount ()); int columnC = (model->columnCount ()); for (int i = 0; i < columnC; ++i) { xlsx->write (1,i+1,model->headerData (i,Qt::Horizontal).toString ()); } for (int i = 0; i < rowC; ++i) { for (int j = 0; j < columnC; ++j) { xlsx->write ((i+2),(j+1), model->record (i).value (j).toString ()); } } if (!fileName.isEmpty()) { if(xlsx->save()) QMessageBox::warning (this,"Correct","数据导出成功"); else QMessageBox::warning (this,"Error","数据导出失败"); }
4 系统的打包和测试
4.1 Mac系统上打包Qt
需要使用otool和macdeployqt两个工具,otool用于定位适用的动态链接库文件,macdeployqt用于对生成的Release版本的程序进行打包。
具体步骤如下:
(1)用Qt Creator编译生成Release版本程序,并测试通过;
(2)进入build-q***-Qt_5_2_1_clang_64-Release文件夹;
(3)在命令行下使用“otool –L”命令查看适用的动态链接库文件,如图所示。如缺少文件,添加到环境变量中;
otool输出结果
(4)在命令行下使用macdeployqt进行打包。下图为打包后应用结构图:
打包应用结构
(5)生成的App文件再使用Disk Utility程序封装,就可以发布了;
4.2 Windows系统上打包Qt。
使用windeployqt工具生成需要打包的文件夹时,会漏掉一些文件,因此需要手动添加一些动态链接库。具体步骤如下:
(1)用VirtualBox 建立Windows 7虚拟机,安装Qt开发完整的平台;
(2)将QtXlsx源程序拷贝到虚拟机中,安装Perl5,编译安装该模块;
(2)将待打包应用程序源代码拷贝到虚拟机中,编译成Realse版本应用;
(3)将应用拷到一个独立文件夹中用windeployqt,生成需要的动态链接库文件;
(4)将其他需要的动态链接库文件从Qt安装目录中拷贝到该目录中;
动态链接文件图
(5)使用inno setup工具对该目录进行封装即可发布了。
Inno Setup
4.3 发布软件测试
测试采用白盒测试,在Virtual Box分别建立全新的Mac OSX,Windows XP和Windows 7
操作系统虚拟机,将打包程序分别拷贝到相应的系统平台中。分别安装并测试系统功能是否符合要求。如果不符合,需要重新编程、编译、打包和测试,直到满意为止。
5 Qt开发常见问题
5.1 ui文件转换为头文件问题
有时Qt Creator编译时会出现一些问题,提示缺少ui_***.h头文件。这是Qt系统出现了问题,解决方法是手动将ui文件转换为相应的头文件。如对***.ui文件,使用:
$ uic ***.ui -o ui_***.h
将其手动的转换为相应的头文件就可以编译了。
5.2 Mac打包时出现不包含“libmysqlclient.18.dylib”问题
在Mac系统中打包可能出现缺少“libmysqlclient.18.dylib”文件问题,这是因为系统没有安装MySQL。解决方法是先安装,macport,然后使用macport安装MySQL。由于默认libmysqlclient.18.dylib文件位置不在搜索目录中,还需要将其拷贝到相应的目录中。
5.3 添加应用图标
对于Windows应用,需要建立一个rc文件说明ico图标文件,在pro文件中添加rc文件。表 为一个示例:
Myapp.rc: IDI_ICON1 ICON DISCARDABLE "myappico.ico" Myapp.pro: RC_FILE = myapp.rc
对于Mac应用,需要生成图片转成为icns文件,然后在pro文件中添加icns文件:
ICON = myapp.icns
参考文献
[1] Qt . [EB/OL].http://qt-project.org/
[2] Qt wiki. [EB/OL].http://zh.wikipedia.org/zh-cn/qt
[3] SQLite. [EB/OL].http://sqlite.org/
[4] SQLite Manager . [EB/OL].https://addons.mozilla.org/zh-CN/firefox/addon/sqlite-manager/
[5] GIMP. [EB/OL].http://www.gimp.org/
[6] Inno setup tools. [EB/OL]. http://www.jrsoftware.org/isinfo.php
[7] Virtual Box. [EB/OL]. https://www.virtualbox.org/
[8] OpenOffice. [EB/OL]. http://www.openoffice.org/zh-cn/
[9] yEd. [EB/OL]. http://www.yworks.com/en/products_yed_about.html
[10] QtXlsx. [EB/OL]. http://qtxlsx.debao.me/
[11] Java. [EB/OL]. http://www.java.com/zh_CN/
[12] Xamarin. [EB/OL]. http://xamarin.com/
[13] Mono. [EB/OL]. http://www.mono-project.com/Main_Page
[14] Java. [EB/OL]. http://openjdk.java.net/
[15]Qt 帮助. [EB/OL]. http://qt-project.org/doc/
【转贴】-- 基于QT的跨平台应用开发的更多相关文章
- 基于QT的webkit与ExtJs开发CB/S结构的企业应用管理系统
一:源起 1.何为CB/S的应用程序 C/S结构的应用程序,是客户端/服务端形式的应用程序,这种应用程序要在客户电脑上安装一个程序,客户使用这个程序与服务端通信,完成一定的 ...
- 基于Qt5 跨平台应用开发
1.Qt简介 2.Qt 编程关键技术 2.1 信号与槽 2.2 Qt事件处理 3.Qt开发与实例分析 3.1 开发环境 3.2 系统实现基本框架 3.3 数据库管理 3.5 对Excel进行操作 4. ...
- 基于ArcGIS Viewer for Flex开发的一款跨平台的应用程序
特点: 1.基于ArcGIS Viewer for Flex开发的一款跨平台的应用程序: -(IBAction) showTOC:(id)sender { if (_tocViewController ...
- 基于QT开发的第三方库
基于Qt开发的第三方库 分类: Qt2014-02-12 11:34 1738人阅读 评论(0) 收藏 举报 QT第三方库 目录(?)[+] 文章来源:http://blog.csdn.net ...
- 【Qt编程】基于Qt的词典开发系列--后序
从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...
- 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计
本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...
- 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计
这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...
- 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计
我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...
- 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示
去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...
随机推荐
- service对象
Service 对象 提供用于创建服务程序的一组工具 语法 Shell.Service[.property|method] 属性 Description 服务描述,仅限于 Windows 2000 及 ...
- jsp动作标签概述
*Jsp动作标签概述: >动作标签的作用是用来简化java脚本 >jsp动作标签是JavaWeb内置的动作标签,它们是已经定义好的动作标签,我们可以拿来直接使用. >JavaWeb一 ...
- 基于Linux 的VM TOOLS Install
VMware Tools Install 在VMware中为Linux系统安装VM-Tools的详解教程 如果大家打算在VMware虚拟机中安装Linux的话,那么在完成Linux的安装后,如果没 ...
- 用Python给你的博客加上水印
之前写的博客里面用到的图片都没有加水印,今天才在别的网站上发现自己的博客居然一个字不动的出现在了别人的文章里,而且还不标注出处,简直醉了. 其实博客这种东西讲真我是很愿意让别人看得,因为自己写的也比较 ...
- NHibernate系列文章十六:使用程序集管理NHibernate项目(附程序下载)
摘要 在实际的项目中,经常是将NHibernate的实体关系映射类做成独立的工程(assembly dll),只对外提供Session调用的接口.这个程序集作为数据访问层,可以被上面的多个工程(ASP ...
- ArcGIS生成根据点图层生成等值面并减小栅格锯齿的操作步骤
一.打开ArcMAP并加载上相应的点图层和边界面图层 二.ArcToolbox--Spatial Analyst工具--差值分析--克里金法(根据不同的情况选择不同的算法,这次的处理实际上使用的是样条 ...
- oracle sql优化
整理一下网上所看到sql优化方法 1.使用大写字母书写sql,因为oracle解释器会先将sql语句转换成大写后再解释 2 减少访问数据库的次数,多数情况下一条sql可以达到目的的,就不要使用多 ...
- maven 加入本地jar包
Apache Maven,由Apache软件基金会所提供.基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建.报告和文档等步骤.曾是Jakarta项目的子项目,现 ...
- windbg学习!vad
在ring0 !address不能提供详细的信息了 可以尝试用下!vad !vad扩展显示一个或多个虚拟地址详细的虚拟地址描述符(virtual address descriptor (VAD)). ...
- swift 代码添加lable
let lable1 = UILabel(frame: CGRect(x: CGFloat(self.view.bounds.width/2-20), y: CGFloat(history.frame ...