《重学C++》11. 实现项目《慕影》的通用组件模块

11-1 QT和VS的项目使用

在QtCreator中创建一个项目后,例如名叫DemoPro1。为了能够使该项目在VS中运行,需要在项目目录下执行命令:

1
qmake -tp vc DemoPro1.pro

之后会生成一个“项目名.vcxproj”等文件,如“DemoPro1.vcxproj”,之后即可通过该文件使用Visual Studio运行。

11-2 QT项目的基础架构类和UI类

常用的Qt开发工具:

工具 说明
qmake 核心的项目构建工具,可以生成跨平台的 .pro 项目文件,并能依据不同操作系统和编译工具生成相应的 Makefile,用于构建可执行程序或链接库。
uic User Interface Compiler,用户界面编译器,Qt 使用 XML 语法格式的 .ui 文件定义用户界面,uic 根据 .ui 文件生成用于创建用户界面的 C++ 代码头文件,比如 ui_*.h 。
moc Meta-Object Compiler,元对象编译器,moc 处理 C++ 头文件的类定义里面的 Q_OBJECT 宏,它会生成源代码文件,比如 moc_*.cpp ,其中包含相应类的元对象代码,元对象代码主要用于实现 Qt 信号/槽机制、运行时类型定义、动态属性系统。
rcc Resource Compiler,资源文件编译器,负责在项目构建过程中编译 .qrc 资源文件,将资源嵌入到最终的 Qt 程序里。
qtcreator 集成开发环境,包含项目生成管理、代码编辑、图形界面可视化编辑、 编译生成、程序调试、上下文帮助、版本控制系统集成等众多功能, 还支持手机和嵌入式设备的程序生成部署。
assistant Qt 助手,帮助文档浏览查询工具,Qt 库所有模块和开发工具的帮助文档、示例代码等都可以检索到,是 Qt 开发必备神器,也可用于自学 Qt。
designer Qt 设计师,专门用于可视化编辑图形用户界面(所见即所得),生成 .ui 文件用于 Qt 项目。
linguist Qt 语言家,代码里用 tr() 宏包裹的就是可翻译的字符串,开发人员可用 lupdate 命令生成项目的待翻译字符串文件 .ts,用 linguist 翻译多国语言 .ts ,翻译完成后用 lrelease 命令生成 .qm 文件,然后就可用于多国语言界面显示。
qmlscene 在 Qt 4.x 里是用 qmlviewer 进行 QML 程序的原型设计和测试,Qt 5 用 qmlscene 取代了旧的 qmlviewer。新的 qmlscene 另外还支持 Qt 5 中的新特性 scenegraph 。

QApplication:是 Qt 的标准应用程序类,继承关系:

QApplication<-QGuiApplication<-QCoreApplication<-QObject;

11-3 QQString的基本使用

QString:是Qt中的字符串类,和C++默认string类类似。下面的代码介绍了QString类的基本使用、查找下标、截取中间子串、获取长度、字符串和数字相互转换操作;

11-4 QDebug的基本使用

QDebug:因为程序前端窗口不能输出信息,因此借助该类进行调试。下面的代码介绍了使用QDebug输出简单的调试信息

这两部分的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
QString str = "C:\\";
QString str2 ("D:/");
str.append("windows\\"); //str == "C:\\windows\\"
str2 += "muying/"; //str2 =="D:/muying/"
qDebug() << str << endl;
qDebug() << str2 << endl;
//string: length & substr & find index
str2 = str2.mid(str.indexOf("\\"),QStringLiteral("muying").length());

//number to str
QString str3 = QString::number(199);
qDebug() << "The value of str is: " << str3 << endl;
qDebug("The value of str is: %s", qPrintable(str3));
//str to number
QString str4 = "12345";
int i = str4.toInt();
qDebug() << "The value of i is: " << i << endl;
QString str5 = "abc";
int j = str5.toInt(); //如果不能转换为数字,将返回0
qDebug("The value of j is: %d", j);

输出信息:

“C:\windows\“
“D:/muying/“
The value of str is: “199”
The value of str is: 199
The value of i is: 12345
The value of j is: 0

11-5 QT的智能指针QScopedPointer

QScopedPointer智能指针有两种:单个变量指针和数组指针。

这部分内容涉及内置类型的指针、自定义类型指针、数组指针、指针的reset操作,下面的代码为示例:

1
2
3
4
5
6
7
8
9
10
11
12
//添加作用域,在该大括号外里面的变量消亡
{
QScopedPointer<int> p(new int(2));
*p = 10;
qDebug() << *p << endl;
p.reset(new int(3));
qDebug() << *p << endl;

QScopedPointer<SPC> SPCp(new SPC());
SPCp->print();
QScopedArrayPointer<SPC> SPCpp(new SPC[3]);
}

在括号外加上断点,会看到程序输出:

1
2
3
4
5
6
7
8
9
10
10 3 
SPC()
print()
SPC()
SPC()
SPC()
~SPC()
~SPC()
~SPC()
~SPC()

即使没有运行到return(),但是构造的对象还是会被释放。

11-6 QThread的使用

QThread是Qt中的线程类,需要引入<QThread>或<Qthread.h>头文件才能使用。

声明和定义一个自定义的线程MyThread类,需要继承QThread类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

class MyThread :public QThread {
public:
MyThread();
~MyThread();
void closeThread() {
isStop = true;
}
void run() {
while (true)
{
if (isStop)
{
return;
}
qDebug() << tr("MyThread id is: ") << QThread::currentThreadId() << endl;
sleep(2);
}
}
private:
bool isStop;//标记停止,当true时run函数无法执行有效功能
};

MyThread::MyThread()
{
isStop = false;
}

MyThread::~MyThread()
{
isStop = true;
}

main函数内:

1
2
3
4
5
6
7
8
//实现多线程
MyThread t;
t.start();
while (true)
{

}
t.closeThread();

运行后会不断输出线程id,例如:

“MyThread id is: “ 0x17e0

更好的方法是通过点击按钮等触发运行t.closeThread(),后面学到前端将会讲到。