C++是一种通用的标准编程语言,使用任何编辑器都可以编写C++源程序,然后利用C++编译器对程序进行编译,就可以生成可执行的程序。
为了方便进行C++程序的编写和编译,有各种综合开发环境(Integrated Developing Environment,IDE),如Visual Studio就是Windows平台上常见的编写C++程序的IDE。一个IDE不仅提供程序的编辑和编译,一般还提供一套基本类库,用于提供支持平台应用程序开发的各种基本类,如Visual Studio使用MFC进行Windows平台的应用程序开发。
Qt是一套应用程序开发类库,但与MFC不同,Qt是跨平台的开发类库。Qt支持PC和服务器的平台,包,括Windows、Linux、 macOS等,还支持移动和嵌入式操作系统,如iOS、 Embedded Linux、Android、WinRT等。跨平台意味着只需编写一次程序,在不同平台,上无需改动或只需少许改动后再编译,就可以形成在不同平台上运行的版本。这种跨平台功能为开发者提供了极大的便利。
Qt最早是由挪威的Haavard Nord和Eirik Chambe-Eng在1991年开始开发的,在1994年发布, 并成立了一家名为Trolltech的公司。Trolltech公司在2008年被诺基亚公司收购。2012年,Qt被Digia公司收购,并在2014年成立了独立的Qt公司,专门 ]进行Qt的开发、维护和商业推广。
经过20多年的发展,Qt已经成为最优秀的跨平台开发框架之一,在各行各业的项目开发中得到广泛应用。许多大型软件都是用Qt开发的,如Autodesk Maya、Google Earth、Skype、 WPS Office等。
Qt是C++类库,而qtcreater是一款IDE。包括:
Assistant是一个独立的查看Qt帮助文件的程序,集成在了Qt Creator中。Designer是- 个独立的进行窗口、对话框等界面可视化设计的程序。Designer也集成在了Qt Creator中,在Qt Creator中编辑或创建界面文件时,就可以自动打开并进行界面设计。Linguist是一 一个编辑语言资源文件的程序,在开发多语言界面的应用程序时会用到。每个编译器又有Build和Run两个设置界面。在Build设置界面上,有一个“Shadow build"复选框。如果勾选此项,编译后将在项目的同级目录下建立一个编译后的文件目录,目录名称包含编译器信息,这种方式一般用于使用不同编译器创建不同版本的可执行文件。如果不勾选此项,编译后将在项目的目录下建立“Debug"和“Release"子目录用于存放编译后的文件。
要在Qt Creator里调试MSVC2015编译的程序,必须安装Windows软件开发工具包SDK。 要在VS中使用QT,也需要安装插件,并进行一些设置。
项目管理文件用于记录项目的一些设置,以及项目包含文件的组织管理。 “Qt += core gui"表示项目中加入core gui模块。core gui是Qt用于GUI设计的类库模块,如果创建的是控制台(Console) 应用程序,就不需要添加core gui。 Qt类库以模块的形式组织各种功能的类,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。例如,如果项目中使用到了涉及数据库操作的类就需要用到sq|模块,在pro文件中需 要增加如下一-行:
QT += sqlsamp2_1.pro中的第2行是:
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets这是个条件执行语句,表示当Qt主版本大于4时,才加入widgets模块。 “TARGET = samp2_ 1"表示生成的目标可执行文件的名称,即编译后生成的可执行文件是samp2_1.exe。 “TEMPL ATE = app"表示项目使用的模板是app,是一-般的应用程序。 后面的SOURCES、HEADERS、FORMS 记录了项目中包含的源程序文件、头文件和窗体文件(.ui文牛)的名称。这些文件列表是Qt Creator自动添加到项目管理文件里面的,用户不需要手动修改。当添加一个文件到项目,或从项目里删除一个文件时,项目管理文件里的条目会自动修改。
main(函数是应用程序的入口。它的主要功能是创建应用程序,创建窗口,显示窗口,并运行应用程序,开始应用程序的消息循环和事件处理。 QApplication是Qt的标准应用程序类,第1行代码定义了-个QApplication类的实例a,就是应用程序对象。 然后定义了-个Widget类的变量w,Widget是本实例设计的窗口的类名,定义此窗口后再用w.show0显示此窗口。 最后一行用a.exec0启动应用程序的执行,开始应用程序的消息循环和事件处理。
信号与槽(Signal & Slot)在面向对象的编程方法中,都会创建很多的实例,每个实例都是单独的,要想每个实例能够协同合作,那么就会需要一种对象间传递消息的机制,在很多框架中都采用回调函数来进行对象间信息传递。
回调是一个指向函数的指针,如果想要一个处理函数通知一些事件,你需要将这个指针传递给处理函数。处理函数在适当时间调用回调函数。MFC就是使用的回调函数,但回调可能是不直观的,不易于理解的,并且也不能保证是类型安全的。
Qt为了消除回调函数等的弊端,从而Qt开发了一种新的消息传递机制,即信号和槽。
例如,当我们要求鼠标点击某个按钮时,对应的窗口就需要关闭,那么这个按钮就会发出一个关闭信号,而窗口接收到这个信号后执行关闭窗口。那么,这个信号就是按钮被点击,而槽就是窗口执行关闭函数。
Qt4和Qt5都可以使用这种连接方式
static QMetaObject::Connection connect( const QObject *sender, //信号发送对象指针 const char *signal, //信号函数字符串,使用SIGNAL() const QObject *receiver, //槽函数对象指针 const char *member, //槽函数字符串,使用SLOT() Qt::ConnectionType = Qt::AutoConnection//连接类型,一般默认即可 ); //例如 connect(pushButton, SIGNAL(clicked()), dialog, SLOT(close()));Qt5新增这种连接方式,这使得在编译期间就可以进行拼写检查,参数检查,类型检查,并且支持相容参数的兼容性转换。
static QMetaObject::Connection connect( const QObject *sender, //信号发送对象指针 const QMetaMethod &signal,//信号函数地址 const QObject *receiver, //槽函数对象指针 const QMetaMethod &method,//槽函数地址 Qt::ConnectionType type = Qt::AutoConnection//连接类型,一般默认即可 ); //例如 connect(pushButton, QPushButton::clicked, dialog, QDialog::close);当我们想要点击一个按钮,并且想将预先定好的参数一同发送出去时,由于按钮的点击事件clicked()并没有参数,那么按照一般的做法就会先定义一个槽与clicked()信号关联,然后获取参数,再通过自定义的信号将该参数发送出去。
这个过程无疑是繁琐的,为此,Qt提供了QSignalMapper这个类来解决这个问题。同时,这个类可以连接多个按钮,匹配发送信号的对象对应的整数、字符串,窗口指针,继承于QObject的对象参数重新发送它们。
当多个信号连接一个槽时,有时需要判断是哪个对象发来的,那么可以调用sender()函数获取对象指针,返回为QObject指针。
QObject* sender() ;当我们不需要信号槽连接时,可使用disconnect()进行解绑定。其写法和connect一样,只需要将connect换成disconnect即可。
Qt是一个用标准C++编写的跨平台开发类库,它对标准C++进行了扩展,引入了元对象系统、信号与槽、属性等特性,使应用程序的开发变得更高效。本章将介绍Qt的这些核心特点,对于理解和编写高效的Qt C++程序是大有帮助的。
本章还介绍 头文件中Qt的一些全局定义,包括数据类型、函数和宏等,介绍Qt的容器类及其相应迭代器的使用方法。这些全局定义和容器类在程序中经常用到,了 解其原理便于理解后面遇到的一些实例程序。
Qt类库中大量的类是以模块形式分类组织的,包括基本模块和扩展模块等,本章对这些模块做个总体的介绍。一个模块通常就是一个编程主题,如数据库、图表、网络等,本书后面的章节一般是每章介绍一个编程主题。
main.cpp
#include <QApplication> #include "myfirstwidget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MyFirstWidget w; w.show(); return a.exec(); }QApplication: 如果所创建的是一个窗口应用程序,那么必须要有且只有一个这样的实例,在创建QApplication实例后,会自动将指针赋值给Qt的全局变量qApp,如果想在其它地方使用QApplication实例,则可以直接调用qApp。
因为QApplication实例会进行大量的初始化工作,所以要在使用任何对象之前就创建QApplication实例,因此,main函数开头便创建了QApplication实例。
如果创建的是一个非窗口的应用程序,那么可以调用QCoreApplication来创建实例。
QApplication主要做以下事情(只需了解即可): 1:使用用户的桌面设置,初始化应用程序,例如窗口的调色板,字体等。 2:执行事件处理。 3:也可根据命令行参数,设置自己的内部状态。 4:制定窗口样式,颜色调配,文字国际化。 5:设置剪切板,管理鼠标事件。
a.exec(): 进入Qt的主循环事件。当调用exit()函数时,才会退出循环,退出main函数。当程序在准备退出主循环时,会发出aboutToQuit()信号,如果有某些在退出程序前要处理的事情,可链接此信号进行处理。除了主循环外,Qt还有本地循环,可以理解为子循环
myfirstwidget.h
#ifndef MYFIRSTWIDGET_H #define MYFIRSTWIDGET_H #include <QWidget> namespace Ui { class MyFirstWidget; } class MyFirstWidget : public QWidget { Q_OBJECT public: explicit MyFirstWidget(QWidget *parent = 0); ~MyFirstWidget(); private: Ui::MyFirstWidget *ui; }; #endif // MYFIRSTWIDGET_HQ_OBJECT: Q_OBJECT宏,必须在类的私有声明中声明这个宏,这样就可以使用Qt的信号槽机制,元对象系统,对象树等Qt特有的功能,否则无法使用。所以这里推荐在创建类时,最好加上此声明,这样的代码会得到很多Qt提供的便利接口。