QT-跨平台C++图形用户界面应用程序开发框架
一句话介绍
它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。
很多嵌入式软件、桌面工具都是用QT来开发的,包括Quartus和Cadence也有用到QT。诚然,QT也是类似于C#、JAVA那样,专门用来开发图形界面的。
QT优点
- QT有优良的跨平台特性:QT支持下列操作系统: Microsoft Windows 95/98, Microsoft Windows NT, Linux, Solaris, SunOS, HP-UX, Digital UNIX (OSF/1, Tru64),Irix,FreeBSD, BSD/OS, SCO, AIX, OS390,QNX 等等。
- 面向对象
- QT 的良好封装机制使得 QT 的模块化程度非常高,可重用性较好,对于用户开发来说是非常 方便的。 QT 提供了一种称为 signals/slots 的安全类型来替代callback,这使得各个元件 之间的协同工作变得十分简单。
- 丰富的 API(接口)
- QT 包括多达 250 个以上的 C++ 类,还提供基于模板的 collections, serialization, file, I/O device, directory management, date/time 类。甚至还包括正则表达式的处理 功能。
- 支持 2D/3D 图形渲染,支持 OpenGL,大量的开发文档,XML 支持。
使用QT开发的优秀软件:
Autodesk MotionBuilder, professional 3D character animation software
Autodesk Maya, 3D建模和动画软件
Avidemux, a Free Software program designed for multi-purpose video editing and processing
Avogadro:高级分子编辑器
Emergent:神经网络模拟器。
FreeCAD, a free and open source 3D-Solid and general purpose design CAD/CAE
Google地球(Google Earth):三维虚拟地图软件。
Opera:著名的网页浏览器。
Skype:一个使用人数众多的基于P2P的VOIP聊天软件。
Spotify, music streaming service.
TeamSpeak:跨平台的音效通信软件
VirtualBox:虚拟机软件。
VLC多媒体播放器:一个体积小巧、功能强大的开源媒体播放器。
Xconfig:Linux的Kernel配置工具
YY语音: 又名“歪歪语音”,是一个可以进行在线多人语音聊天和语音会议的免费软件。在中国大陆拥有庞大的用户群。
咪咕音乐:咪咕音乐是中国移动倾力打造的正版音乐播放器
WPS Office:金山公司(Kingsoft)出品的办公软件,与微软Office兼容性良好,个人版免费。
QT 三大核心机制
信号槽
信号和槽是用于对象之间的通信的,这是Qt的核心。为此Qt引入了一些关键字,他们是slots、signals、emit,这些都不是C++关键字,是Qt特有的,这些关键字会被Qt的moc转换为标准的C++语句。Qt的部件类中有一些已经定义好了的信号和槽,通常的作法是子类化部件类,然后添加自已的信号和槽。
因为信号和槽与函数相似,所以通常把信号称为信号函数,槽称为槽函数。
其基本思想如下:
创建一个信号,其中创建信号需要一些规则
当需要调用外部函数时,发送一个信号
此时与该信号相关联的槽便会被调用,槽其实就是一个函数,当然要使函数成为槽是有一定规则的。槽与信号的关联需要由程序员来完成。
在Qt中,信号和槽都需要位于类之中。
示例(具体实现时Qt引入了一些新的关键字):
信号槽简单实例
定义信号
1
2
3
4
5
6
7
8
9
10
11
12
class A : public QObject
{
Q_OBJECT
public:
A(QObject* parent = 0);
signals:
void message_arrive(QString msg);
};1
2
3
4
5#include "a.h"
A::A(QObject* parent) : QObject(parent)
{
}关于信号,有几个特点:
- 信号的定义关键字是signals,不需要添加访问级别的关键字修饰,因信号总是被默认为public的,以便在不同类之间通信。
- 信号总是只有声明,而没有定义体的,这就好比C++的纯虚函数一样。
- 信号和槽之间传递的参数必须对应。
- 信号的返回类型总是void,即没有返回值。
定义槽
1
2
3
4
5
6
7
8
9
10
11
12
class B : public QObject
{
Q_OBJECT
public:
B(QObject* parent = 0);
public slots:
void reflash_text(QString msg);
};1
2
3
4
5
6
7
8
9
10#include "b.h"
B::B(QObject* parent) : QObject(parent)
{
}
void B::reflash_text(QString msg)
{
// TODO:接收信号并处理参数
}槽的访问级别可以设置成public, proteced, private,这个根据具体情况而定;同时需要实现相应的函数体。当然,信号与槽也可以同时定义在同一个对象中。
连接信号与槽
方法调用:QObject::connect(const QObject *asender, const char *asignal,const QObject *areceive, const char *asignal)
1
QObject::connect(a, SIGNAL(message_arrive(QString)), this, SLOT(reflash_text(QString)));
其中a为类A的一个对象的指针; this指向类B的一个对象本身,也就是说这个函数connect()在B中调用。
元对象系统
Qt的类包含Q_OBJECT宏 moc编译器会对该类编译成标准的C++代码
Qt的元对象系统基于如下三件事情:
类:QObject,为所有需要利用元对象系统的对象提供了一个基类。
宏:Q_OBJECT,通常可以声明在类的私有段中,让该类可以使用元对象的特性,比如动态属性,信号和槽。
编译器:元对象编译器(moc)为每个QObject子对象自动生成必要的代码来实现元对象特性。
moc工具会读入C++的源文件,如果它发现了一个或者多个声明了Q_OBJECT宏的类,它就创建另一个C++源文件,为每个类生成包含元对象实现的代码。这些编译生成的源文件通常都已经被包含到类的源文件中或者和类的实现同时被编译和链接。
事件模型
- 事件的创建
鼠标事件,键盘事件,窗口调整事件,模拟事件 - 事件的交付
Qt通过调用虚函数QObject::event()来交付事件。 - 事件循环模型
主事件循环通过调用QCoreApplication::exec()启动,
随着QCoreApplication::exit()结束, - 本地的事件循环可用利用QEventLoop构建。
一般来说,事件是由触发当前的窗口系统产生的,但也可以通过使用 QCoreApplication::sendEvent()和 QCoreApplication::postEvent()来手工产生事件。需要说明的是QCoreApplication::sendEvent()会立即发送事件, QCoreApplication::postEvent()则会将事件放在事件队列中分发。 - 自定义事件