QT开发1

基础

功能

QT Windgets Application: 桌面平台的图形用户界面(GUI)应用程序
QT Console Application: 控制台应用程序,一般用于学习C/C++
Qt Quick Application: 创建可部署的Qt Quick2应用程序。Qt Quick是Qt支持的一套GUI开发架构。采用QML设计界面,程序框架采用C++语言
Qt Quick Controls 2 Application: 创建基于Qt Quick Control2组件的可部署的Qt Quick 2 应用程序。
Qt Canvas 3D Application: 基于QML语言的界面设计,支持3D画布。

QMainWindow:主窗口类,具有主菜单、工具栏和状态栏,类似一般程序的主窗口
Qwidget:是所有具有可视化界面类的基类,各种界面组件都支持
QDialog:对话框类,建立基于对话框的界面

Action Editor:Action编辑器
Signals & Slots Editor:信号与槽

项目配置文件

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
33
34
35
36
37
38
39
QT       += core gui # qt加入core和gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets # 如果qt大于4,就加入 widgets

CONFIG += c++11

TARGET = XXX # 生成exe程序时候,目标文件名字叫 xxx
TEMPLATE = app # 模板类型,应用程序模板 这是一个应用程序

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS # 表示当Qt的某些功能被标记过时的,那么编译器会发出警告

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \ # 源文件
main.cpp \
mainwidget.cpp

HEADERS += \ # 头文件
mainwidget.h

FORMS += \ # ui文件
mainwidget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \ # 资源文件
images.qrc

RC_ICONS = favicon.ico #应用程序图标

Widget:Qwidget窗口:从上大小,继承关系(下面的都是派生类)

信号与槽

发送者 信号 接受者
Botton_close clicked() Widget close()

很重要必须要看的文件

ui_widget.h:
ui_mainwindow.h:

1
Q_OBJECT //宏,使用Qt信号与槽机制必须添加
1
QMetaObject::connectSlotsByName(MainWidget);//按名字连接信号与槽,如果没有这句话就不能使用名字的信号与槽

widget:组件

layout:布局

项目中添加资源文件:文件 -> 新建文件或项目 -> QT ->Qt Resource File->输入名字,创建*.qrc文件
在项目中点击 :open in editor可以打开文件
*.qrc文件点击Add Prefix创建文件,修改相应的前缀, 点击Add Files添加相关文件

要在头文件中编写槽函数必须如下格式:

1
2
3
4
5
class XXX
{
private slots: //私有的槽函数如下
};

槽函数格式:

1
QObject::connect(this->ui->radioButton_black, SIGNAL(clicked()), this, SLOT(setTextFontColor()));

Action :非常有用的类,可以创建菜单项、工具栏按钮

快捷操作、快捷功能

功能 快捷键 解释
Switch Header/Source F4 在同名的头文件和源程序文件之间切换
Follow Symbol Under Cursor F2 变量:跳转到声明;函数:声明和定义切换
Switch Between Function
Declartion and Definition
Shift+F2 函数:声明和定义切换
Refacetor\Rename Symbol
Under Cursor
Ctrl+Shift+R 改名称,将替换所有用到这个符合的地方
Refactor\Add Definitionin .cpp 为函数原型在cpp文件中生成函数体
Auto-indent Selection Ctrl+I 为选择的文字自动进行缩进
Toggle Comment Selection Ctrl+/ 注释或取消注释
Context Help F1 注释或取消注释
Save All Ctrl+Shift+S 文件全部保存
Find/Replace Ctrl+F 调出查找/替换对话框
Build Ctrl+B 编译当前项目
Start Debugging F5 开始调试
Step Over F10 单步(略过)调试,执行当前程序语句
Step Into F11 单步(跟踪)调试,如果当前行里有函数,就跟踪进入函数
Toggle Breakpoint F9 设置或取消当前行的断点

qt核心特点
元对象编译器(meta-object Complier,MOC)是一个预处理器(所谓的元就是:meta在英文词中有超越、更上一层的含义。)
先将Qt的特性程序转换成标准C++程序,再由标准C++编译器进行编译
元对象的意义

使用 处理

Qt为C++语言增加的特性在Qt core模块里实现,由Qt的元对象系统实现包括:信号与槽机制、属性系统、动态类型转换等。

元对象系统 (Meta-Object System)
1.Qobject类是所有使用元对象系统的类的基类
2.在一个类的private部分声明Q_OBJECT宏
3.MOC(元对象编译器)为每个QObject的子类提供必要的代码

qobject_cast(类类型转换) 与 C++语言种 static_cast(数据类型之间转化) 、dynamic_cast

属性系统:

Q_PROPERTY宏定义一个返回类型为type!,名称为name的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
Q_PROPERTY( type name
(READ getFunction[WRITE setFunction] |
MEMBER memberName[(READ getFunction | WRITE setFunction)])
[RESET resetFunction]//复位
[NOTIFY notifySigna]//信号
[REVISION int]//版本
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL]
)

[]:代表可选的

getFunction setFunction 为函数

MEMBER memberNamename 进行绑定,就是键与值

type:类型必须使用通用类型,不能经过转换后的类型,不能使用stdint.h中的类型

类的附加信息

添加这个类,可以通过函数访问类型

1
2
3
Q_CLASSINFO("author","XX")
Q_CLASSINFO("compay","xxx")
Q_CLASSINFO("version","1.0.0")
1
2
3
//类型,可以做调试信息
obj->metaObject()->classInfo(0).name(); // author
obj->metaObject()->classInfo(0).value(); //Wang

参考:https://zhuanlan.zhihu.com/p/516163795

信号与槽定义

1
2
3
4
5
6
7
8
9
10
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member,Qt::ConnectionType = Qt::AutoConnection);//信号与槽函数都是字符串  通用一些

//如果信号和槽函数带有参数,需要注明参数类型
connect(spinNum,SIGNAL(valueChanged(int)),this,SLOT(updateStatus(int)));

QMetaObject::Connection QObject::connect(cosnt QObject *sender,const OMetaMethod &signal,const QObject *receivers,const QMetaMethod &method,Qt::ConnectionType = Qt::AutoConnection)//常用,给了指针
//对于信号名称唯一的(不能有重载,有重载函数只能用上面的),没有参数不同而不同的信号函数
connect(lineEdit,&QLineEdit::textChanged,this,&widget::on_textChanged);

Qt::ConnectionType = Qt::AutoConnection//这是单线程或者多线程的

最后一个参数: Qt::ConnectionType表示了信号与槽之间的关联方式
Qt::AutoConnection(缺省值):自动确定关联方式
Qt::DirectConnection: 信号被发射时,槽立即执行,槽函数与信号在同一线程
Qt::QueuedConnection: 事件循环回到接收者线程后执行槽,槽与信号在不同线程
Qt::BlockingQueueConnection: 与Qt::QueuedConnection相似,信号线程会被阻塞直到槽执行完毕。当槽函数与信号在同一线程,会造成死锁。

在槽函数里,使用QObject::sender()可以获取信号发射者的指针,下面代码是写在槽函数中的,槽函数知道发送信号得类型,可以使用动态类型转换拿到他的指针,然后设置发送者得值和使用值都是可以得

1
QSpinBox*spinbox = qobject_cast<QSpinBox *> (sender())

自定义信号及其使用

1
2
3
4
5
6
7
8
9
10
11
12
class QPerson:public QObject
{
Q_OBJECT
private:
int m_age = 10;
public:
void incAge();//是一个按钮,按下就触发
signals:
void ageChanged(int value);
};

void QPerson::incAge(){m_age++;emit(ageChanged(m_age));//发射信号}

ageChanged:信号函数必须无返回值,但可以有输入参数信号函数无需实现,只需在某些条件下发射信号

explicit:不发生隐式类型转换,从而提高代码的可维护性和可读性,减少潜在的错误和意外行为。

emit(ageChanged(m_age)):发出信号

注意

如果使用的信号与槽是字符串模式:

1
connect(this->ui->spinBox_Boy,SIGNAL(valueChanged(int)),this,SLOT(on_spin_valueChanged(int)));

则槽函数必须要写在类的槽函数下,否则无法调用

1
2
private slots:
void on_spin_valueChanged(int arg1);

如果使用的信号与槽是指针模式:

1
connect(boy,&Qperson::ageChanged,this,&Widget::on_AgeChanged);

槽函数可以不用写在类的:private slots:

QT全局定义(Global:全局的意思)

<QtGlobal>头文件包含了qt类库的一些全局定义
1.基本数据类型 2.函数 3.宏
因为太常用,所以不用显示的包含,QT类的头文件都会包含该文件(函数类型的定义必须使用这些变量定义,不要使用#include<cstdint>

注意如下两条

  1. qreal 缺省是8字节double类型浮点数,如果Qt使用 -qreal float 选项进行配置,就是4字节float 类型的浮点数

  2. qfloat16 是Qt5.9.0中新增的一个类用于表示16位的浮点数,要使用gfloat16,需要包含头文件<QFloat16>

全局函数定义

函数 功能
T qAbs(const T &value) 返回变量value的绝对值
const T&qBound(const T &min,const T &value,const T & max) 返回value限定在min至max范围之内的值
bool qFuzzyCompare(double p1,double p2)
bool qFuzzyCompare(float p1,float p2)
若p1和P2近似相等,返回true
Fuzzy:近似的
float必须大于5位数据是相同的才能近似相等
double
bool qFuzzylsNull(double d) 如果参数d约等于0,返回true
double qlnf() 返回无穷大的数
bool qlsFinite(double d) 若d是一个有限的数,返回true
bool qlslnf(double d) 若d是一个无限大的数,返回true
bool qlsNaN(double d) 若d不是一个数,返回true
const T&qMax(const T&value1,const T&value2) 返回value1和value2种最大的值
const T&qMin(const T&value1,const T&value2) 返回value1和value2种最小的值
qint64 qRound64(double value) 将value近似为最接近的qint64整数
int qRound(double value) 将value近似为最接近的int整数
int qrand() 标准C++中rand()函数的线程安全型版本,
返回0至RAND_MAX之间的伪随机数
void qsrand(uint seed) 标准C++中srand()函数的线程安全型版本,
使用种子seed对伪随机数字序列初始化

还有一些基础的数学运算函数在 <QtMath> 头文件中定义,比如三角运算函数、弧度与角度之间的转换函数等。

QT_VERSION: 这个宏展开为数值形式0xMMNNPP (MM = major, NN = minor, PP = patch) 表示Qt编译器版本,例如Qt编译器版本为Qt 5.9.1,则 QT_VERSION 为 0x050901。这个宏常用于条件编译设置,根据Qt版本不同,编译不同的代码段。

QT_VERSION_CHECK: 这个宏展开为 Qt 版本号的一个整数表示

源码:

1
2
3
4
5
6
7
8
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
#define QT_VERSION QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH)
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))

示例:

1
2
3
4
5
#if QT_VERSION >= 0x051402
/*code*/
#else
/*code*/
#nedif

QT_VERSION_STR: 这个宏展开为Qt版本号的字符串,如“5.9.0”

Q_BYTE_ORDER、Q_BIG_ENDIAN和Q_LTTLE_ENDIAN: Q_BYTE_ORDER表示系统内存中数据的字节序,Q_BIG_ENDIAN 表示大端字节序,Q_LITTLE_ENDIAN 表示小端字节序。在需要判断系统字节序时会用到

Q_DECL_IMPORT和Q_DECL_EXPORT:在使用或设计共享库时,用于导入或导出库的内容后续章节有其使用实例。

Q_DECL_OVERRIDE: 在类定义中,用于重载一个虚函数,例如在某个类中重载虚函数paintEvem(),可以定义如下:

void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE使用该宏后,如果重载的虚函数没有进行任何重载操作,编译器将会报错

C++中的虚函数关键字virtual

Q_DECL_FINAL: 这个宏将一个虚函数定义为最终级别,不能再被重载,或定义一个类不能再被继承

1
2
3
4
5
class QRect Q_DECL_FINAL	//QRect 不能再被继承
{

}

Q_UNUSED(name): 这个宏用于在函数中定义不在函数体里使用的参数

1
2
3
4
5
void MainWindow::on_imageSaved(int id, const QString &fileName)
{
Q_UNUSED(id);
Lablnfo->setText("图片保存为:"+fileName);
}

foreach(variable,container): 用于容器类的遍历

1
2
foreach (const QString &codecName, recorder->supportedAudioCodecs())
ui->comboCodec->addltem(codecName);

例如recorder有三个值遍历三次,每次的值都传给codeName

forever: 用于构造一个无限循环

1
2
3
4
forever
{
//中间要退出要有相应代码,类似 while
}

qDebug(const char* message,..) : 在debugger窗体显示信息,如果编译器设置了Qt_NO_DEBUG_OUTPUT,则不作任何输出

1
qDebug("ltems in list: %d", myList.size());

类似的宏还有 qWarning、gCritical、gFatal、glnfo 等,也是用于在 debugger 窗体显示信息

字符串与数值之间的转换

1.QString类可以显示字符串与数值之间的转换;

2.使用QLable、QLineEdit显示和输入信息;

3.使用布局

QString类从字符串转换为整数的函数有:

1
2
3
4
5
int toInt(bool *ok = Q_NULLPTR,int base = 10);//bool *ok 是否转换成功,这里存储了结果  base:如果需要修改进制,就可以修改这里
const long toLong(bool *ok = Q_NULLPTR,int base = 10);
const short toShort(bool *ok = Q_NULLPTR,int base = 10);
const uint toUInt(bool *ok = Q_NULLPTR,int base = 10);
const ulong toULong(bool *ok = Q_NULLPTR,int base = 10)const;

QString 将字符串转换为浮点数的函数有:

1
2
double toDouble(bool *ok = Q_NULLPTR)const
float toFloat(bool * ok= Q_NULLPTR)const

希望显示两位小数,下面4行语句都可以实现这个功能

1
2
3
4
str = QString::number(total,'f',2);//静态成员方法 total是数字,转换成浮点数,保留2位小数
str = QString::asprintf("%.2f",total);
str = str.setNum(total,'f',2);//对象
str = str.sprintf("%.2f",total);

字符串与输入输出

QString的常用功能
QString存储字符采用的是Unicode码,(16位Qchar)

append()和prepend()

后面添加或者前面添加字

1
2
3
4
QString str1 = "卖",str2 = "拐";
QString str3 = str1;
str1.append(str2); //str1 = 卖拐
str3.prepend(str2); //str2 = 拐卖

oUpper()和toLower() 字符转换成大写或小写

1
2
3
QString str1 = "Hello World",str2;
str2 = str1.toUpper(); //str2 = "HELLO WORLD"
str2 = str1.toLower(); //str2 = "hello world"

count()、size()和length()

1
2
3
4
QString str1 = "NI好"
N = str1.count() //N = 3
N = str1.size() //N = 3
N = str1.length() //N = 3

trimmed()和simplified() 掐头去尾,空格合并

1
2
3
QString str1 = " Are    you    OK? ",str2;
str2 = str1.trimmed(); //str1 = "Are you OK?"
str2 = str1.simplified() //str1 = "Are you OK?"

indexOf() 和 lastlndexOf()

indexOf:从头开始找,找到字符串中,第一个与输入的字段匹配的位置,

lastlndexOf:从字符串末尾开始寻找,找到与输入字段匹配的位置

1
2
3
4
5
//int indexOf(const QString &str,int from = 0, QT::CaseSensitivity cs = Qt::CaseSensitive)const 
//需要找str字符串种特点字符,从那个位置开始找 from ,默认区分大小写 cs
QString str1 = "G:\QT_5_PRO\sampl6_1\sampl6_1\main.cpp";
N = str1.indexOf("5_");//n = 7,找到字符串中第一个与"5_"匹配的字段,返回位置。
N = str1.lastlndexOf("\\"); //n = 29 从末尾开始寻找,这里双斜杠是代表斜杠,只不过是找的最后一个斜杠,返回位置

endsWith和startsWith

以某个字段结尾或者开始,返回真与假

1
2
3
QString str1 = "G:\QT_5_PRO\sampl6_1\sampl6_1\main.cpp";
bool value = str1.endsWith(".cpp"); //value = true
value = str1.startsWith("G:"); //value = true

contains

是否包含字段

1
2
QString str1 = "G:\QT_5_PRO\sampl6_1\sampl6_1\main.cpp";
bool value = str1.endsWith(".cpp"); //value = true

isNull()和isEmpty()

未赋值字符串 空字符串

isNull:只要变量存在,就不是空(有\0),除非指向空指针,

1
2
3
4
5
QString str1,str2 = "";
N= str1.isNull(); N= true 未赋值字符串变量
N= str2.isNull(); N = flase 只有'\0'的字符串,也不是Null
N= str1.isEmpty();N= true
N= str2.isEmpty();N= true

QString 只要赋值,就在字符串的末尾自动加上”\0”,如果只要判断字符串内容释放为空,常用isEmpty()

left和right 字符截断

left:函数用于从字符串的左侧截取指定数量的字符。

参数:n 表示要截取的字符数量。

返回值:返回一个包含最左边 n 个字符的 QString 对象。如果 n 大于或等于字符串的长度,则返回整个字符串。如果 n 小于0,则返回整个字符串。

right:函数用于从字符串的右侧截取指定数量的字符。

返回值:left() 函数返回的是字符串的子串副本,不会修改原始字符串。

边界条件:当 n 大于字符串长度时,返回整个字符串。当 n 小于0时,返回整个字符串。

right:与上面相反

1
2
3
4
QString str = "Hello, World!";
QString leftPart = str.left(5); // 返回 "Hello"
QString rightPart = str.right(6); // 获取从最后一个字符开始的5个字符,即"World!"
qDebug() << rightPart; // 输出: "World!"

section()

字符串分段,用什么符号分段,从什么位置开始(那一段开始), 到什么位置结束(那一段结束)

1
2
3
4
5
6
7
QString section(const QString &sep,int start , int end = -1, SectionFlags flags = SectionDefault) const
QString str2,str1 = "学生姓名,男,19xx-3-4,汉族,山东";
str2 = str1.section(",",0,0);
//str2="学生姓名",第1段的编号为 0
str2 = str1.section(",",1,1); //str2 = "男"
str2 = str1.section(",",0,1); //str2= "学生姓名,男"
str2 = str1.section(",",4,4); //str2 = "山东"

SpinBox的使用

QSpinBoxQDoubleSpinBox都是QAbstractSpinBox的子类

属性名称 描述
prefix 数字显示的前缀,例如”$“
suffix 数字显示的后缀,例如”KG“
minimum 数值范围的最小值,如0
maximum 数值范围的最大值,如255
singlestep 单击右侧上下调整按钮时的单步改变值,如设置为1,或0.1
value 当前显示的值
displaylntegerBase(显示整数基数) QSpinBox特有属性,显示整数使用的进制,例如2就代表二进制,显示按照几进制显示
decimals(小数点) QDoubleSpinBox特有属性,显示数值的小数位数,例如2就显示两位小数

其他数值输入和显示组件

QSlider:滑动条,通过滑动设置数值,可用于数值输入。

QScrollBar:卷滚条,与QSlider功能类似,还可以用于卷滚区域

QProgressBar:进度条,一般用于显示任务进度,可用于数值的百分比显示。

QDial:表盘式数值输入组件,通过转动表针获取输入值。

QLCDNumber:模仿LCD数字的显示组件,可以显示整数或浮点数,显示整数可以使用不同进制数值。

QRadioButton 组件

当该组件没有分配到一个组合的时候,是可以同时选中多个的,当分配到一个组合之后,就只能单选。

日期时间数据与字符串之间的转换

QTime:时间数据类型,如15:23:13

QDate:日期数据类型,如2017-02-15

QDateTime:日期时间数据类型,如 2017-03-15 20:23:56

QDataEdit:编辑和显示日期的组件

QDateTimeEdit:编辑和显示日期时间的组件

QCalendarWidget:一个用日历形式选择日期的组件

QTimer:定时器,如果周期为100,那么每100毫秒会发射一次timeout信号

输出格式

字符 意义
d 天,不补零显示,1-31
dd 天,补零显示,01-31
M 月,不补零显示,1-12
MM 月,补零显示,01-12
yy 年,两位显示,00-99
yyyy 年,四位显示,例如 2000
h 小时,不补零显示,0-23或0-12(显示AM/PM)
hh 小时,补零2位显示,00-23或00-12(显示AM/PM)
H 小时,不补零显示,0-23(即使显示AM/PM)
HH 小时,补零显示,00-23(即使显示AM/PM)
m 分钟,不补零显示,0-59
mm 分钟,补零显示,00-59
z 毫秒,不补零显示 0-999
zz 毫秒,补零3位显示 000-999
AP或A 使用AM/pm显示
ap或a 使用am/pm显示