QT模块

QT基础,模块主要分为:
//1、QT COre
提供核心的非 GUI 功能,所有模块都需要这个模块。这个模块的类包括了动画框架、
定时器、各个容器类、时间日期类、事件、IO、JSON、插件机制、智能指针、图形(矩形、路径等)、
线程、XML 等。所有这些类都可以通过 头文件引入。
//2、QT GUI
提供 GUI 程序的基本功能,包括与窗口系统的集成、事件处理、OpenGL 和 OpenGL ES 集成、2D 图像、
字体、拖放等。这些类一般由 Qt 用户界面类内部使用,当然也可以用于访问底层的 OpenGL ES 图像 API。
Qt Gui 模块提供的是所有图形用户界面程序都需要的通用功能。
//3、QT Multimedia
提供视频、音频、收音机以及摄像头等功能。这些类可以通过 引入,
而且需要在 pro 文件中添加 QT += multimedia。
//4、QT Network
提供跨平台的网络功能。这些类可以通过 引入,而且需要在 pro 文件中添加 QT += network。
//5、QT Qml
提供供 QML(一种脚本语言,也提供 JavaScript 的交互机制) 使用的 C++ API。这些类可以通过 引入,
而且需要在 pro 文件中添加 QT += qml。
//6、QT Quick
允许在 Qt/C++ 程序中嵌入 Qt Quick(一种基于 Qt 的高度动画的用户界面,适合于移动平台开发)。
这些类可以通过 引入,而且需要在 pro 文件中添加 QT += quick。
//7、QT SQL
允许使用 SQL 访问数据库。这些类可以通过 引入,而且需要在 pro 文件中添加 QT += sql。
//8、QT Test
提供 Qt 程序的单元测试功能。这些类可以通过 引入,而且需要在 pro 文件中添加 QT += testlib。
//9、QT Webkit
基于 WebKit2 的实现以及一套全新的 QML API(顺便说一下,Qt 4.8 附带的是 QtWebkit 2.2)。

Qt 扩展模块则有更多的选择:

Qt 3D,提供声明式语法,在 Qt 程序中可以简单地嵌入 3D 图像。Qt 3D 为 Qt Quick 添加了 3D 内容渲染。Qt 3D 提供了 QML 和 C++ 两套 API,用于开发 3D 程序。
Qt Bluetooth,提供用于访问蓝牙无线设备的 C++ 和 QML API。
Qt Contacts,用于访问地址簿或者联系人数据库的 C++ 和 QML API。
Qt Concurrent,封装了底层线程技术的类库,方便开发多线程程序。
Qt D-Bus,这是一个仅供 Unix 平台使用的类库,用于利用 D-Bus 协议进行进程间交互。
Qt Graphical Effects,提供一系列用于实现图像特效的类,比如模糊、锐化等。
Qt Image Formats,支持图片格式的一系列插件,包括 TIFF、MNG、TGA 和 WBMP。
Qt JS Backend,该模块没有公开的 API,是 V8 JavaScript 引擎的一个移植。这个模块仅供 QtQml 模块内部使用。
Qt Location,提供定位机制、地图和导航技术、位置搜索等功能的 QML 和 C++ API。
Qt OpenGL,方便在 Qt 应用程序中使用 OpenGL。该模块仅仅为了程序从 Qt 4 移植到 Qt 5 的方便才保留下来,如果你需要在新的 Qt 5 程序中使用 OpenGL 相关技术,需要使用的是 QtGui 模块中的 QOpenGL。
Qt Organizer,使用 QML 和 C++ API 访问组织事件(organizer event)。organizer API 是 Personal Information Management API 的一部分,用于访问 Calendar 信息。通过 Organizer API 可以实现:从日历数据库访问日历时间、导入 iCalendar 事件或者将自己的事件导出到 iCalendar。
Qt Print Support,提供对打印功能的支持。
Qt Publish and Subscribe,为应用程序提供对项目值的读取、导航、订阅等的功能。
Qt Quick 1,从 Qt 4 移植过来的 QtDeclarative 模块,用于提供与 Qt 4 的兼容。如果你需要开发新的程序,需要使用 QtQuick 模块。
Qt Script,提供脚本化机制。这也是为提供与 Qt 4 的兼容性,如果要使用脚本化支持,请使用 QtQml 模块的 QJS* 类。
Qt Script Tools,为使用了 Qt Script 模块的应用程序提供的额外的组件。
Qt Sensors,提供访问各类传感器的 QML 和 C++ 接口。
Qt Service Framework,提供客户端发现其他设备的服务。Qt Service Framework 为在不同平台上发现、实现和访问服务定义了一套统一的机制。
Qt SVG,提供渲染和创建 SVG 文件的功能。
Qt System Info,提供一套 API,用于发现系统相关的信息,比如电池使用量、锁屏、硬件特性等。
Qt Tools,提供了 Qt 开发的方便工具,包括 Qt CLucene、Qt Designer、Qt Help 以及 Qt UI Tools 。
Qt Versit,提供了对 Versit API 的支持。Versit API 是 Personal Information Management API 的一部分,用于 QContacts 和 vCard 以及 QOrganizerItems 和 iCalendar 之间的相互转换。
Qt Wayland,仅用于 Linux 平台,用于替代 QWS,包括 Qt Compositor API(server)和 Wayland 平台插件(clients)。
Qt WebKit,从 Qt 4 移植来的基于 WebKit1 和 QWidget 的 API。
Qt Widgets,使用 C++ 扩展的 Qt Gui 模块,提供了一些界面组件,比如按钮、单选框等。
Qt XML,SAX 和 DOM 的 C++ 实现。该模块已经废除,请使用 QXmlStreamReader/Writer。
Qt XML Patterns,提供对 XPath、XQuery、XSLT 和 XML Schema 验证的支持。
这里需要强调一点,由于 Qt 的扩展模块并不是 Qt 必须安装的部分,因此 Qt 在未来版本中可能会提供更多的扩展模块,这里给出的也仅仅是一些现在确定会包含在 Qt 5 中的一部分,另外还有一些,比如 Qt Active、Qt QA 等,则可能会在 beta 及以后版本中出现。

Qt 4 也分成若干模块,但是这些模块与 Qt 5 有些许多不同。下面是 Qt 4 的模块:

QtCore,Qt 提供的非 GUI 核心类库,这一部分与 Qt 5 大致相同,只不过 Qt 4 的 core 类库中并不包含 JSON、XML 处理等。
QtGui,图形用户界面组件,这个模块相当于 Qt 5 的 QtGui 与 QtWidgets 两个模块的总和。
QtMultimedia,多媒体支持,类似 Qt 5 的相关部分。
QtNetwork,网络支持,类似 Qt 5。
QtOpenGL,提供对 OpenGL 的支持。在 Qt 5 中,这部分被移植到 QtGui 模块。
QtOpenVG,提供对 OpenVG 的支持。
QtScript,提供对 Qt Scripts 的支持。Qt Script 是一种类似于 JavaScript 的脚本语言。在 Qt 5 中,推荐使用 QtQml 的 JavaScript 部分。
QtScriptTools,为 Qt Script 提供的额外组件。
QtSql,提供对 SQL 数据库的支持。
QtSvg,提供对 SVG 文件的支持。
QtWebKit,提供显示和编辑 Web 内容。
QtXml,XML 处理,这部分在 Qt 5 中被添加到了 QtCore。
QtXmlPatterns,提供对 XQuery、XPath 等的支持。
QtDeclarative,用于编写动画形式的图形用户界面的引擎。
Phonon,多媒体框架。
Qt3Support,Qt 3 兼容类库。
下面是 Qt 4 的一些工具模块:

QtDesigner,用于扩展 Qt Designer。
QtUiTools,用于在自己的引用程序中处理 Qt Designer 生成的 form 文件。
QtHelp,联机帮助。
QtTest,单元测试。
下面是专门供 Windows 平台的模块:

QAxContainer,用于访问 ActiveX 控件。
QAxServer,用于编写 ActiveX 服务器。
下面是专门供 Unix 平台的模块:

QtDBus,使用 D-Bus 提供进程间交互。

MainWindow简介
新建工程时,QT Creator会帮助我们新建一个MainWindow。
QT4中没有widgets模块,因此在pro文件中,需要手写一段代码(新建项目的时候好像会自动生成)
QT += core gui //添加模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
//如果QT的主版本号(QT_MAJOR_VESION)大于4,需要另外添加widget(在QT5中,所有组件都是在widget模块中定义的)

TARGET = qtdemo
TEMPLATE = app
//TARGET是生成的程序的名字
SOURCES += main.cpp
mainwindow.cpp

HEADERS += mainwindow.h
//SOURCES 和 HEADERS 顾名思义,就是项目所需要的源代码文件和头文件

添加动作
QT使用QAction类作为动作,QT没有专门的菜单项类,只使用一个QAction类,抽象出公共的动作。
把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。
用户可以通过点击菜单项、点击工具栏按钮、快捷键来激活这个动作。

QAction包括了图标、菜单文字、快捷键、状态栏文字、浮动帮助等信息

代码举例:
// !!! Qt 5
// ========== mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();

private:
void open();

QAction *openAction;

};

#endif // MAINWINDOW_H
// ========== mainwindow.cpp
#include
#include
#include
#include
#include

#include “mainwindow.h”

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setWindowTitle(tr(“Main Window”));

openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, &QAction::triggered, this, &MainWindow::open);

QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);

QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);

statusBar() ;

}

MainWindow::~MainWindow()
{
}

void MainWindow::open()
{
QMessageBox::information(this, tr(“Information”), tr(“Open”));
}

main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);

MainWindow win;
win.show();

return app.exec();

}
分析:
首先,在MainWindow类中添加一个私有函数open()和一个私有变量openAction。在MainWindow的构造函数中,
第一行我们调用了setWindowTitle(),设置主窗口的标题。注意我们的文本使用tr()函数,
这是一个用于 Qt 国际化的函数。可以使用 Qt 提供的国际化工具,将tr()函数的字符串提取出来,进行国际化。
由于所需进行国际化的文本应该被大多数人认识,所以,tr()函数里面一般会是英文文本。

然后,在堆上创建了openAction对象。在QAction构造函数,我们传入了一个图标、一个文本和 this 指针。
图标我们使用了QIcon,传入值是一个字符串,这个字符串对应于 Qt 资源文件中的一段路径。
Qt 资源文件的后缀名是 qrc。如果我们使用 Qt Creator,我们可以在新建文件中看到 Qt 资源文件。
Qt 资源文件其实是一个 XML 描述的文件,表示 Qt 应用程序所需要的各个资源。我们可以使用普通文本编辑器打开这个文件:


document-open.png

//需要复习的知识点:构造函数、堆和栈
我们会在后面的章节中详细介绍 Qt 资源文件(注意,资源文件需要在 pro 文件中使用 RESOURCES 引入。)。这里只需要了解,
QIcon的参数,以 : 开始,意味着从资源文件中查找资源。:/images/doc-open就是找到了这里的 document-open.png 这个文件。
(我们使用的是 png 格式的图片,这是 Qt 内置支持的图片格式。其他格式的图片,比如 jpg、gif 则需要插件支持。这些插件实际已经随着 Qt 一同发布。)

QAction第二个参数中,文本值前面有一个 &,意味着这将成为一个快捷键。
下面一句,我们使用了setShortcut()函数,用于说明这个QAction的快捷键。Qt 的QKeySequence为我们定义了很多内置的快捷键,
比如我们使用的 Open。你可以通过查阅 API 文档获得所有的快捷键列表。 这个与我们自己定义的有什么区别呢?简单来说,
我们完全可以自己定义一个tr(“Ctrl+O”)来实现快捷键。原因在于,这是 Qt 跨平台性的体现。比如 PC 键盘和 Mac 键盘是不一样的,
一些键在 PC 键盘上有,而 Mac 键盘上可能并不存在,或者反之。使用QKeySequence类来添加快捷键,会根据平台的不同来定义相应的快捷键。

setStatusTip()则实现了当用户鼠标滑过这个 action 时,会在主窗口下方的状态栏显示相应的提示。
后面的connect()函数,将这个QAction的triggered()信号与MainWindow类的open()函数连接起来。当用户点击了这个QAction时,会自动触发MainWindow的open()函数。

下面的menuBar()、toolBar()和statusBar()三个是QMainWindow的函数,用于创建并返回菜单栏、工具栏和状态栏。我们可以从代码清楚地看出,
我们向菜单栏添加了一个 File 菜单,并且把这个QAction对象添加到这个菜单;同时新增加了一个 File 工具栏,也把QAction对象添加到了这个工具栏。
我们可以看到,在菜单中,这个对象被显示成一个菜单项,在工具栏变成了一个按钮。至于状态栏,则是出现在窗口最下方,用于显示动作对象的提示信息的。

// !!! Qt 4
// ========== mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:
void open();

private:
QAction *openAction;
};

#endif // MAINWINDOW_H
// ========== mainwindow.cpp
#include
#include
#include
#include

#include “mainwindow.h”

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setWindowTitle(tr(“Main Window”));

openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);

QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);

statusBar();

}

MainWindow::~MainWindow()
{
}

void MainWindow::open()
{
QMessageBox::information(this, tr(“Information”), tr(“Open”));
}

资源文件
详解看这个
https://www.devbean.net/2012/08/qt-study-road-2-resource-files/

对象模型
QT扩展了标准C++,所谓“扩展”,实际是在使用标准 C++ 编译器编译 Qt 源程序之前,
Qt 先使用一个叫做 moc(Meta Object Compiler,元对象编译器)的工具,
先对 Qt 源代码进行一次预处理(注意,这个预处理与标准 C++ 的预处理有所不同。
Qt 的 moc 预处理发生在标准 C++ 预处理器工作之前,并且 Qt 的 moc 预处理不是递归的。),
生成标准 C++ 源代码,然后再使用标准 C++ 编译器进行编译。如果你曾经为信号函数这样的语法感到奇怪
(现在我们已经编译过一些 Qt 程序,你应当注意到了,信号函数是不需要编写实现代码的,那怎么可以通过标准 C++ 的编译呢?),
这其实就是 moc 进行了处理之后的效果。

Qt 使用 moc,为标准 C++ 增加了一些特性:

◾信号槽机制,用于解决对象之间的通讯,这个我们已经了解过了,可以认为是 Qt 最明显的特性之一;
◾可查询,并且可设计的对象属性;
◾强大的事件机制以及事件过滤器;
◾基于上下文的字符串翻译机制(国际化),也就是 tr() 函数,我们简单地介绍过;
◾复杂的定时器实现,用于在事件驱动的 GUI 中嵌入能够精确控制的任务集成;
◾层次化的可查询的对象树,提供一种自然的方式管理对象关系。
◾智能指针(QPointer),在对象析构之后自动设为 0,防止野指针;
◾能够跨越库边界的动态转换机制。

通过继承QObject类,我们可以很方便地获得这些特性。当然,这些特性都是由 moc 帮助我们实现的。
moc 其实实现的是一个叫做元对象系统(meta-object system)的机制。正如上面所说,
这是一个标准 C++ 的扩展,使得标准 C++ 更适合于进行 GUI 编程。虽然利用模板可以达到类似的效果,
但是 Qt 没有选择使用模板。按照 Qt 官方的说法,模板虽然是内置语言特性,但是其语法实在是复杂,
并且由于 GUI 是动态的,利用静态的模板机制有时候很难处理。而自己使用 moc 生成代码更为灵活,
虽然效率有些降低(一个信号槽的调用大约相当于四个模板函数调用),不过在现代计算机上,这点性能损耗实在是可以忽略。

在前面例子中用到的parent指针的解释:
QObject是以对象树的形式组织起来的。当创建一个QObject对象时,会看到QObject的构造函数接收一个Qobject
指针作为参数,这个参数就是parent,也就是父对象指针。这就相当于,在创建QObject对象时,可以提供一个
其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。当父对象析构的时候,这个列表中的
所有对象也会被析构。(注意:这里的父对象并不是继承意义上的父类!)
这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。

QWidget 是能够在屏幕上显示的一切组件的父类。QWiget继承自QObject,因此也继承了这种对象树关系。
一个孩子自动地成为父组件的一个字组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。
例如,当用户关闭一个对话框的时候,应用程序将其删除,属于这个对话框的按钮、图标也一起被删除。

也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除一个工具栏时,其所在的主窗口会自动将工具栏从其字对象列表中
删除,并且自动调整屏幕显示。

调试可以使用的函数:QObject::dumpObjectTree()和QObject::dumpObjectinfo()

QT 引入对象树的概念,在一定程度上解决了内存问题。

当一个QObjec对象在堆上创建的时候,QT会同时为其创建一个对象树,不过,对象中对象树的顺序是没有定义的。
这意味着,销毁这些对象的顺序也是未定义的。QT保证的是,任何对象树中的Object对象delete的时候,如果这个
对象有parent,则自动将其从parent的children()列表中删除,如果有孩子,则自动delete每一个孩子。QT保证
没有QObject会被delete两次,这是由析构顺序决定的。

如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段:
{
QWidget window;
QPushButton quit(“Quit”, &window);
}

作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。
这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++ (ISO/IEC 14882:2003)要求,
局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,
将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。

但是,如果我们使用下面的代码:
{
QPushButton quit(“Quit”);
QWidget window;

quit.setParent(&window);

}
情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,
因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。
然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。
但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐