韩元旭、余橙、沈开洋正则表达式
Qt是一个跨平台的C++图形用户界面应用程序框架。它早在1991年奇趣科技公司两位合伙人着手开发这样一个平台,在2008年如日中天的诺基亚因为看好Qt在嵌入式领域的潜力,一掷千金将它收购做为新一代智能手机操做系统的载体,可是由于诺基亚在智能手机领域的败北,不得已而放手Qt,终于Qt于2012被最后一位东家 Digia 公司收购。通过这几年的发展,Qt不但拥有了完备的C++图形库,并且也极大的提升了Qt开发跨平台应用程序的能力。数据库
Qt能够同时支持桌面应用程序开发、嵌入式开发和移动开发,甚至它能够作移动开发,覆盖了现有的全部主流平台。你只须要编写一次代码,发布到不一样平台前从新编译便可。编程
Qt凭借一套对原生Windows、Mac、Linux等平台支持很好的 GUI 库和丰富的 API 库,使得它成为了开发跨平台桌面应用的一个很好的选择。与中国一些优秀的桌面端软件选择本身开发多平台的 GUI 库不一样,国外的不少优秀桌面应用都偏好采用跨平台的 GUI 库进行开发。好比在硅谷有一款很著名的文档管理应用 DropBox,微软自家的社交聊天工具 Skype,像极品飞车这样大型的游戏的GUI页面,甚至国内的金山软件公司推出的办公软件 WPS Office,固然还有咱们的AlphaBox。浏览器
由于Qt不只可以高效率的完成不一样平台GUI内容的开发,更可以高效率的完成系统级别的一些任务。这也是AlphaBox选择使用Qt开发的缘由。安全
AlphaBox 其实包含两个主要的进程,一块是同步盘的引擎—C语言构建的底层同步进程,咱们称之为 daemon;剩下的图形页面以及与操做系统交互的模块都是使用Qt进行开发的。Qt提供的丰富的跨平台GUI组件可以保证在不一样操做系统中 AlphaBox 都有着美观和吻合操做系统的样式,Qt自家生产的 IDE—Qt Creator 提供了一套很是好上手的图形界面构建工具,即便是刚接触Qt的小白也能够轻松的绘制出想要的页面而且可以完成核心页面逻辑。除此以外,得益于 C++ 的加持,Qt与操做系统有着很是健壮的通讯机制,凭借这一点,AlphaBox 可以轻松完成精准监控操做系统中文件的改动、创建本地数据库进行写入数据的等操做,不只于此,优秀的混合编程能力可以让Qt轻松的与 Objective-C、C# 等语言进行混编,实现系统级别扩展的调用,这就是咱们可以在 Finder 和Windows 资源管理器中可以看到同步盘文件不一样状态的缘由了。bash
Qt支持 Windows、Linux/Unix、Mac OS X、Android、BlackBerry、QNX等多种平台,并为这些不一样的平台提供了统一的开发环境。多线程
C++是彻底面向对象的,这一点和Objective-c等在开发很类似。而Qt又是基于C++一种语言的扩展,你们都知道C++ 有快速、简易、面向对象等不少优势,因此Qt天然也继承者C++这些的优势。框架
Qt良好的封装机制使得Qt的模块化程度很是高,可重用性较好,对用户开发来货是很是方便的。Qt提供一种为signals/slots(信号和槽) 的安全类型来替代callback,使得各个元件之间的协同工做变得十分简单。模块化
Qt包括多达 250 个以上的 C++ 类,还提供基于模板的 collections, serialization, file, I/Odevice, directory management, date/time 类。甚至还包括正则表达式的处理功能。
支持 2D/3D 图形渲染,支持 OpenGL。
大量的开发文档。函数
Webkit 引擎的集成,能够实现本地界面与Web内容的无缝集成, 可是真正使得 Qt 在自由软件界的众多 Widgets (如 Lesstif,Gtk,EZWGL,Xforms,fltk 等等)中脱颖而出的仍是基于 Qt 的重量级软件 KDE。
Qt提供了信号和槽机制用于完成见面操做的响应,是完成任意两个Qt对象之通讯机制。其中,信号会在某个特定状况或动做下被触动,槽是等同于接受并处理信号的函数。
为何方法不是直接调用的。中间用到 Signal 和槽机制不是画蛇添足?
其实在咱们生活也是同样,老板级别的好说话,老板给助理分派任务也好说话,可是助理给老板分任务,可想而知会有什么后果,在之前的统治阶层确定不容许这样的事发生。因此在分层思想中,咱们所调用的函数也是这样的,上层能够调用下层和同一层的函数,下层函数不能够调用上层函数,不然程序的层次性会被打破,致使结构错综复杂,难以维护和管理。
那么怎样才能作到向上管理呢,有任务分配给老板怎么办?
老板会设立一个机构,也就是一个函数,用无限循环来查询助理的状态,若是助理真的有事情,这个机构就把这消息拿到老板来处理。可是这种处理方式显得有些复杂,咱们想要的简单明了的方式是,若是助理有事件发生,能够直接调用
老板函数处理。
说了这么多其实就是想说,信号和槽的最大优点在于,它完善了程序分层的思想,能够在不改变程序的层次性的状况下,完成由下层到上层的调用。在下层发出一个 Signal,这时上层与其想关联的 Slot 函数就会响应。
如今,信号和槽中存在的问题是:
要想解决以上问题,就须要将相应的信号和槽链接起来。当指定的信号发出时,槽所在的对象就能接收到该信号,从而调用相应的槽函数执行指定的处理。
1.一个信号能够与另外一个信号相连
connect (Object1,SIGNAL(signal1),Object2,SIGNAL(signal2));
复制代码
表示 Object1的信号1发送能够触发Object2的信号1发送。
2.同一个信号能够与多个槽相连:
connect (Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect (Object1,SIGNAL(signal2),Object3,SIGNAL(slot1));
复制代码
3.同一个槽能够响应多个信号:
connect (Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect (Object3,SIGNAL(signal2),Object2,SIGNAL(slot2));
复制代码
4.链接能够被移除:
这种状况用得比较少,由于在对象被删除时,Qt会自动移除与这个对象相关的全部链接。
disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));
复制代码
可是,经常使用的链接方式为:
connect (Object1,SIGNAL(signal),Object2,SIGNAL(slot));
复制代码
其中,signal 为对象Object1的信号,slot 为Object2的槽。
####提示: 信号与槽机制与普通函数的调用同样,若是使用不当的话,在程序执行时也有可能产生死循环。所以,在定义槽函数时必定要注意避免间接造成无限循环,即在槽中再次发射所接收到的一样信号。
若是一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。
宏定义不能用在 signal 和 slot 的参数中。
信号和槽的参数个数与类型必须一致。
须要关联的信号和槽的签名必须是等同。即信号的参数类型和参数个数 同接收该信号的槽的参数类型和参数个数相同。不过一个槽的参数个数是能够少于信号的参数的个数的,可是缺乏的参数必须是信号参数的最后一个或者几个参数。若是信号和槽的签名不符,编译器就会报错。
信号和槽机制大大下降了Qt对象的耦合度。发送信号的Qt对象不须要知道是哪一个对象来接收它的信号,它只须要作的是在适当的时间发送一个信号,并且不须要知道也不关心它的信号有没有被接收到,更不须要知道哪一个对象的哪一个槽接收到了信号。
一样地,Qt对象的槽也不须要关系是哪些信号链接了本身,若是信号和槽链接上了,Qt就能保证了适合的槽获得了调用。即便关联的对象在运行时被删除。应用程序也不会崩溃。
信号和槽机制加强了对象间通讯的灵活性,固然在增长灵活性的同时在性能方面也会有必定的损失。同你们回调函数相比,信号和槽机制运行速度有些慢。一般,经过传递一个信号来调用槽函数将会比直接调用直接调用非虚函数运行速度慢10倍。
缘由:
然而,与建立堆对象的new操做及删除堆对象的delete操做相比,信号和槽的运行代价只是它们不多一部分。信号和槽机制致使的这点性能损耗,对实时应用程序是能够忽略的;同信号和槽提供的灵活性和简便性相比,这点性能损耗是值得的。
做为一名 iOS 开发人员, 见证着 iOS 布局系统的不断完善, 从绝对布局, Autoresizing 到 Autolayout. 使得开发人员的工做效率愈来愈高, 项目界面的可读性和易维护性愈来愈强. 现在 IDE 中的可视化界面工具已经很是强大, 许多网友"戏称" iOS 开发者为"UI 拖拽师", 可见, iOS 开发中界面布局系统的高效. 因此, 优秀的布局系统的使命在于让开发者花更少的时间来完成更易维护的界面.
一样的, 在 Qt 中, 系统提供了强大的排版机制来为窗口中的视图进行布局排版, 通过了对 Qt 布局一个初步的探索, 不得不对 Qt 布局系统的简洁高效而又功能强大表示赞叹.
在 Qt 中, 布局系统能够完成
Qt 提供了 QLayout 类及其子类来为界面进行排版布局. 结构以下图:
QLayout 是布局系统中的抽象基类, 继承自 QObject 和 QLayoutItem, 其中四个子类分别为
在真实使用场景中, 每每须要经过多种布局的相结合来完成界面的设计, 接下来将分别介绍四中布局.
箱式布局提供了两个子类分别处理水平(QHBoxLayout)和垂直(QVBoxLayout)两个方向的排版, 可使视图排成一行或者一列来显示. 简单说, 就是可让控件进行排排站, 好比在咱们的 AlphaBox 中, 顶部的头像, 姓名, 和刷新按钮排成了一排, 这就是水平箱式布局:
你觉得我要讲一下这个东西如何实现? NO, 我恰恰要以垂直箱式布局为例, 用一个最简单的例子来介绍箱式布局的使用, 首先建立一个基于 QWidget 的界面, 添加咱们须要使用的头文件:
#include <QVBoxLayout>
#include <QPushButton>
复制代码
并在构造函数中添加以下代码
// 添加两个按钮
QPushButton *okBtn = new QPushButton;
okBtn ->setText(tr("我在上面, 我最牛"));
QPushButton *celBtn = new QPushButton;
celBtn->setText(tr("我在下面, 我不服"));
// 建立一个垂直箱式布局, 将两个按钮扔进去
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(okBtn);
layout->addWidget(celBtn);
// 设置界面的布局为垂直箱式布局
setLayout(layout);
复制代码
运行看一下效果, 什么? 这就能够运行了? 坐标呢? 尺寸呢? 是的, 没看错...点击运行:
两个按钮已经一上一下, 乖乖的在垂直方向本身站好了位置, 就是这么强大, 就是这么省心.
强大的 AlphaBox 是很外向的, 能够很轻松的将你的资料分享给其余用户, 当咱们分享的时候, 会有这样一个界面:
看到这个界面, 聪明的你可能会说, 这很简单啊, 好几个水平箱式布局就能够实现, 但是, 更聪明的 Qt 提供了更高效的方式帮助你完成这样一个界面, 那就是 QFormLayout.
在我所学习 Qt 所使用的书籍中, 将 QFormLayout 翻译为窗体布局, 我我的认为, 将其翻译为表单布局更为贴切, 由于 QFormLayout 的强大之处正是可使用最快的速度完成一个用户输入的表单界面的搭建.
那么, 让咱们揭开 AlphaBox 的神秘面纱, 看看这样一个界面是怎么实现的.
首先, 拖拽一个 Form Layout 到 Widget 中.
双击以后便可为表单增长一行.
相信你们看到这张图时, 就已经能理解到表单布局是如何使用的, 提供了标签做为用户输入内容的指引, 提供字段类型做为用户输入的控件, 做为 iOS 开发者, 深知这样一个界面的搭建所须要的繁杂的工做量. 当我第一次打开这个界面时, 被这样建立界面的方式所惊呆了.
快不快? 快不快! 快不快!!!
一样的, 若是是使用纯代码表单布局的话可使用addRow()
的方法来添加一行.
事实上, 强大的 AlphaBox 是这样的, 咱们能够共享给多个用户, 并且, 下方会有一个列表, 展现共享的用户以及权限列表. 这时, 表单布局就没办法知足咱们, 只好另求新欢 QGridLayout - 网格布局.
网格布局顾名思义, 能够将界面分割成行列来进行布局管理, 在每一个单元格中来摆放控件. 因此 AlphaBox 分享的界面使用了一个 两行三列 的网格布局来实现的.
固然, 更更复杂的界面, 用 Qt 布局的效率也是很是高的, 我作了一个外链分享的布局 Demo, 能够将内部资料生成一个下载连接共享给任何人去下载.
这个界面中, 我在Tab以内使用了网格布局, 布局如图:
从图中能够看出, 网格布局像是在操做一个 Excel 同样简单, 布局单元格, 合并单元格, 等等.
在这个界面中, 更灵活的使用了 QLayout 的属性来完成了界面布局排版.
一样的, 在代码中, 可使用以下等的 Api 来为网格视图添加一个从几行几列开始占据几行几列的控件:
void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan) 复制代码
如在 AlphaBox 中, 咱们能够经过云端文件浏览器直接查看和操做云端文件, 在加载的过程当中, 会有一个转菊花的界面.
加载失败时的错误提示:
以及加载成功时:
一般应用的界面会根据不一样的状态有不一样的内容, 这时就可使用 QStackedLayout 栈布局, 栈布局提供了一个页面的栈, 每一个页面有彻底独立的界面布局. 能够很是清晰的对不一样状态下的界面进行布局管理.
在 Qt 的可视化布局工具中, 经过 Stacked Widget 来完成界面的栈布局
经过右键来进行页面的插入移除和排序等操做.
在接下来的文章中咱们会从搭建项目起,分模块的更加深刻的介绍Qt开发,敬请期待!