1.全局定义
在文件中, 包含了Qt类库中的一些全局定义,包括基本数据类型,函数和宏
2.基本数据类型
qt的基本数据类型存在的目的就是为了保证各个平台中的数据长度保持一致,其中qfloat16,需要包含头文件QFloat16,就是16位浮点数
Qt数据类型 | 等效定义 | 字节数 |
qint8 | signed char | 1 |
qint16 | signed short | 2 |
qint32 | signed int | 4 |
qint64 | long long int | 8 |
qlong | long long int | 8 |
quint8 | unsigned char | 1 |
quint16 | unsignedshort | 2 |
quint32 | unsigned int | 4 |
quint64 | unsigned long long int | 8 |
qulonglong | unsigned long long int | 8 |
uchar | unsigned char | 1 |
ushort | unsigned short | 2 |
uint | unsigned int | 4 |
ulong | unsigned long | 8 |
qreal | double | 8 |
qfloat16 | 2 |
3.容器类
Qt提供了很多容器类(基于模板的), 这样可以很方便的存储指定类型的数据项,每种容器类都有其处理对应数据项的基本方法
3.1 顺序容器类
顺序容器类就是按照一定的逻辑顺序存储数据项.
3.1.1 QList容器类
实现方式:数组列表
索引方式:数组下标, at()函数
特点:速度快,适用面广
子类:QStringList,更快速的存储字符串列表类数据
方法:.
count()//获得字符串文本行数
常用函数:
QList::insert()
QList::replace()
QList::removeAt()
QList::move()
QList::append()
QList::prepend()
QList::isEmpty()
QList::at()
4.元对象
4.1元对象系统组成:
- QObject类是所有元对象系统的类的基类
- 在类的private中声明Q_OBJECT宏,就可以使用元对象的特性,如动态属性,信号和槽
- MOC元对象编译器,构建项目时,MOC工具会自动读取C++源文件,如果发现Q_OBJECT宏就会为该类自动生成另一个包含元对象支持代码的C++源文件,且会将两个源文件和实现文件一起编译连接(了解即可)
元对象的基本功能
1).设置属性和访问属性
QObject::setProperty()
QObject::property()
//分别是设置属性和访问属性
2).返回关联元对象,metaObject()
const QMetaObject *meta = boy->metaObject();
cout << meta->className() << endl;
cout << meta->propertyCount() << endl;
QObject::metaObject()函数返回 类关联的 元对象,其类型是QMetaObject类;
当然:在类private中使用宏定义Q_OBJECT 使得该类可以用元对象特性
3).元对象类QMetaObject类包含了元对象的一些接口:
QMetaObject::className()//方法在运行时返回相关类的名称字符串
QMetaObject::propertyCount() //返回类的属性的个数
QMetaClassInfo QMetaObject::classInfo(int index) const //获取元对象的附加信息,返回的是QMetaClassInfo类型(见下文:附加了信息)
4).附加类信息
关键字Q_CLASSINFO 用来定义附加类信息
元对象可使用接口函数classInfo()获得对应的附加信息,返回的类型是 QMetaClassInfo类
QMetaClassInfo QMetaObject::classInfo(int index) const
获取附加信息的名称和值
QMetaClassInfo::name()
QMetaClassInfo::value()
//该类封装了两个接口, name()和value()分别获取附加信息的名称和值
//举例
const QMetaObject *meta = boy->metaObject();
QMetaClassInfo qMCI = meta->classInfo(2); //取第2个附加类信息
cout<<qMCI.name()<<endl;
cout<<qMCI.value()<<endl;
4.2 属性系统
属性系统包括了属性的定义和使用,以及动态属性和附加信息的设置和使用
1).属性定义 Q_PROPERTY
//属性定义
Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |
MEMBER memberName [ (READ getFucntion | WRITE setFunction) ] )
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL] )
//解释
Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |
MEMBER memberName [ (READ getFucntion | WRITE setFunction) ] )
//定义1个返回类型是type的,名称是name的属性,
//且用READ和WRITE关键字,关联该属性的写入,读取函数
// 使用READ指定一个读取属性的函数
// 使用WRITE指定一个写入属性的函数
// 使用MEMBER指定一个成员变量和属性关联,可以对属性进行读写
// 此时无需READ和WRITE
//仅把函数名和属性关联,函数自身仍需要声明和定义(同一般方法一致)
//下面关键字分别关联不同的功能,是可选的
[RESET resetFunction] //指定默认属性值的函数
[NOTIFY notifySignal] //指定一个信号,属性值变化时该信号发射
[REVISION int] //版本号
[DESIGNABLE bool] //设置属性能否在QtDesigner中可见
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT] //指定该属性是常数,即不可WRITE和NOTIFY
[FINAL] ) //指定该属性无法被子类重载
2) 属性适用property()与setProperty()
知道属性名,就可以使用QObject::setProperty()设置属性和QObject::property()获取属性
QObject *object = button;
object->setProperty("name", true) //该属性是名为name,返回类型是bool
bool a = object->property("name");
//举例
#ifndef QPERSON_H
#define QPERSON_H
#include <QObject>
class QPerson : public QObject
{
Q_OBJECT
Q_CLASSINFO("author","Wang")
Q_CLASSINFO("company","UPC")
Q_CLASSINFO("version","1.0.0")
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(QString name MEMBER m_name)
Q_PROPERTY(int score MEMBER m_score)
private:
int m_age=10;
QString m_name;
int m_score=79;
public:
explicit QPerson(QString fName, QObject *parent = nullptr);
int age();
void setAge(int value);
void incAge();
signals:
void ageChanged( int value);
public slots:
};
#endif // QPERSON_H
3)动态属性和附加属性
动态属性,在运行时定义的新属性,使用方法同上
附加属性,利用宏Q_CLASSINFO(),为元对象定义"名称-值"的附加信息
class QMyClass : public QObject
{
Q_OBJECT
Q_CLASSINFO("author", "sherlock")
Q_CLASSINFO("version","0.0.1")
public:
private:
private slots:
signals:
};
5.信号与槽函数
5.1 特征标
当信号与槽函数的参数数量相同时,参数类型要一致
当信号的参数与槽函数的参数数量不同时,只能是信号的参数数量多于槽函数的参数数量,且前面相同数量的参数类型应一致,信号中多余的参数会被忽略。
1).特征标一致
//特征标一致
void iSignal(int b);
void MainWindow::iSlot(int b)
{
QString qString;
qDebug()<<qString.number(b);
}
connect(this, SIGNAL(iSignal(int)), this, SLOT(iSlot(int)));
emit iSignal(5);
//output:5
2).特征标不一致
//特征标不一致
void iSignal(int a, float b);
void MainWindow::iSlot(int b)
{
QString qString;
qDebug()<<qString.number(b);
}
connect(this, SIGNAL(iSignal(int)), this, SLOT(iSlot(int)));
emit iSignal(5, 0.3);
//output:5
5.2 定义信号
信号只定义,无需实现,只需要在某情景下发射该信号即可
#ifndef QPERSON_H
#define QPERSON_H
#include <QObject>
class QPerson : public QObject
{
Q_OBJECT
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
//ageChanged信号为自定义信号
private:
public:
signals:
void ageChanged( int value);
//自定义信号,注意无需实现代码,只需发射信号即可
public slots:
};
#endif // QPERSON_H
//发射信号
#include "qperson.h"
QPerson::QPerson(QString fName,QObject *parent) : QObject(parent)
{ //构造函数
m_name=fName;
}
void QPerson::setAge(int value)
{//设置age
m_age=value;
emit ageChanged(m_age); //发射信号
}
5.3 定义槽函数
槽函数可以有传递参数,可以没有,需要用到信号传递的参数时可以设置参数.
//一般在类中声明一个私有方法作为槽函数
class QWDlgManual : public QDialog{
Q_OBJECT
private:
QPushButton *btnOK;
QPushButton *btnCancel;
void iniUI();
void iniSignalSlots();
private slots:
void on_chkBoxUnder(bool checked);
void setTextFontColor(bool checked);
public:
QWDlgManual(QWidget *parent = 0);
~QWDLgManual();
};
5.4 信号和槽的关联
1).常规关联方法, 信号发射主体, 信号,信号发射客体,槽函数
QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
//一般将关联函数放到类构造函数中
2).将类成员函数作为槽函数的关联方法
[static] QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged,
label, &QLabel::setText);
3). 直接定义出函数结构体逻辑的关联方法
[static] QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(1080,720);
this->setFixedSize(this->width(),this->height());
Generate* gen = new Generate(this);
connect(this,&MainWindow::sendParameterA,gen,&Generate::saveParameterA);
connect(ui->pushButton,&QPushButton::clicked,this,[=]()
{
emit sendParameterA(0.09);
gen->start();
}
);
connect(gen,&Generate::sendResult,this,[=](double res) //()内是信号传递的参数
{
QString result;
result = QString::number(res);
ui->plainTextEdit->appendPlainText(result);
});
}
6.字符串
思考,如何把qint或int等变量转换成QString?
6.1 QString类
1) 类型转换(将指定进制的字符串,转换成其他基本类型)
QString转换为其他,可以直接用如下函数, 注意base是指QString的进制数
//不设置参数时,如下函数将默认从十进制字符串转换成整数,否则将指定的进制字符串转换成整数
int toInt(bool *ok = Q_NULLPTR, int base = 10) const;
int toLong(bool *ok = Q_NULLPTR, int base = 10) const;
int toShort(bool *ok = Q_NULLPTR, int base = 10) const;
int toUInt(bool *ok = Q_NULLPTR, int base = 10) const;
int toULong(bool *ok = Q_NULLPTR, int base = 10) const;
double toDouble(bool *ok = Q_NULLPTR) const;
float toFloat(bool *ok = Q_NULLPTR) const;
//ok表示是否转换成功
实例:
//转成整数,浮点数
QString str = ui->editNum->text(); //QLabel/QLineEdit类的读取函数
int num = str.toInt(); //字符串类型转换
str = ui->editPrice->text(); //QLabel/QLineEdit类的读取函数
float price = str.toFloat(); //QString转换成float类型
float total = num*price;
str = str.sprintf("%.2f", total);
ui->editTotal->setText(str); //QLabel/QLineEdit类的显示设置函数
2)字符串显示与进制转换
字符串显示时,可以进行进制转换,这里的赋值相当于打印了
二进制是Binary,简写为B,bin。八进制是Octal,简写为O,oct。十进制为Decimal,简写为D,dec。十六进制为Hexadecimal,简写为H,hex;
number()与asprintf()
number()返回的是QString, toInt()返回的是in
[static] QString QString::number(long n, int base = 10)
QString str;
float total = 2.345678;
str = QString::number(total,'f',2);
str = QString::asprintf("%.2f",total);
str = str.setNum(total,'f',2);
str = str.sprintf("%.2f",total);
//将QString转换成int类型
int val = ui->edit->text().toInt(&ok,2);
int val = ui->edit->text().toInt(&ok,10);
int val = ui->edit->text().toInt(&ok,16);
//将int类型10进制转换成其他进制
QString val = QString::number(val,10);
QString val = QString::number(val,16);
val=val.toUpper();
QString val = QString::number(val,2);
3)常用方法
添加字符.append() 和.prepend()方法
QString str1 = "ab";
QString str2 = "ccc";
str1.append(str2); //末尾追加str2
str2.prepend(str1); //前方追加str1
大小写
str2 = str1.toUpper(); //字符全部大写
str2 = str1.toLower(); //字符全部小写
返回字符串字符个数,汉字也算1个字符
int N;
N = str1.count();
N = str1.size();
N = str1.length();
去空格
str2 = str1.trimmed(); //去首尾空格
str2 = str1.simplified(); //去首尾空格,且中间连续空格用1个空格替换
查找/包含
indexOf()查找的是从指定地址的元素第一次出现的位
N = str1.indexOf("5.0"); //查找字符串中5.0出现的位置
N = str1.lastIndexOf("\\"); //查找字符\最后出现的位置,因为\需要转义所以使用\\表示
int indexOf(const QString &str,
int from = 0,
Qt::CaseSensitivity cs = Qt::CaseSensitive)const;
//其中str为对应字符串的引用,from为查找的起点位置,cs为是否指定大小写
N = str1.constains(".cpp",Qt::CaseInsensitive); //N为bool, 且不区分大小写
N = str1.constains("cpppp",Qt::CaseSensitive); //区分大小写
字符串对象判空
bool B;
B = str1.isNull(); //NULL表示无,即连'\0'也没有,只有未赋值的字符串此时B才为TRUE
B = str1.isEmpty(); //empty表示空,表示仅有'\0'
判断是否以某个字符开头
N = str1.endsWith("a",Qt::CaseInsensitive); //不区分大小写
N = str1.endsWith("a",Qt::CaseSensitive); //区分大小写
N = str1.endsWith("a"); //不区分大小写
截取字符
QString str3;
str3 = str1.left(4);
str3 = str2.right(3);
分割提取
QString section(const QString &sep,
int start, int end = -1;
SectionFlags flags = SectionDefault) const;
//将sep作为分隔符,用分割符切割字符串成多个块,且从0开始排序
str3 = "1,2,3,4,a,5,6";
str1 = str3.section(",",0,0); //str1 = "1"
str1 = str3.section(",",1,1); //str1 = "2"
str1 = str3.section(",",0,2); //str1 = "1,2,3"
str1 = str3.section(",",4,6); //str1 = "a,5,6"
str1 = str3.section(","6,6); //str1 = "6"
QStringList QString::split(const QString &sep,
SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive
) const
QString str = "a,,b,c";
QStringList list1 = str.split(',');
// list1: [ "a", "", "b", "c" ]
QStringList list2 = str.split(',', QString::SkipEmptyParts);
// list2: [ "a", "b", "c" ]
QString str = "abc";
auto parts = str.split("");
// parts: {"", "a", "b", "c", ""}
QString str = "/a/b/c/";
auto parts = str.split('/');
// parts: {"", "a", "b", "c", ""}
状态栏添加进度条,工具栏添加spinbox
状态栏添加一般的QLabel显示在左边, 添加永久的QLabel显示在右边
//mymainwindow.h
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
//包含需要的文件
#include <QMainWindow>
#include <QLabel>
#include <QProgressBar>
#include <QFontComboBox>
#include <QSpinBox>
QT_BEGIN_NAMESPACE
namespace Ui { class myMainWindow; }
QT_END_NAMESPACE
class myMainWindow : public QMainWindow
{
Q_OBJECT //声明该宏则该类可以使用元对象的特性
public:
myMainWindow(QWidget *parent = nullptr);
~myMainWindow();
private:
Ui::myMainWindow *ui;
QLabel *fLabCurFile;
QProgressBar *progressBar1;
QSpinBox *spinFontSize;
QFontComboBox *comboFont;
void iniUI();
};
#endif // MYMAINWINDOW_H
//mymainwind.cpp
#include "mymainwindow.h"
#include "ui_mymainwindow.h"
myMainWindow::myMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::myMainWindow)
{
ui->setupUi(this);
iniUI(); //必须要在setupUI()后,因为setupUI()负责构建一个可视化界面
}
myMainWindow::~myMainWindow()
{
delete ui;
}
//使用iniUI()函数来完成部分界面的设置
void myMainWindow::iniUI()
{
//在状态栏上添加自定义组件 ui->statusbar即ui界面的状态栏
fLabCurFile = new QLabel; //创建一个QLabel对象,用来设置状态栏
fLabCurFile->setMinimumWidth(150); //设置该对象的在状态栏的宽度是150
fLabCurFile->setText("当前文件:"); //设置该对象在状态栏的显示内容
ui->statusbar->addWidget(fLabCurFile); //将该对象添加到状态栏(非永久)
QLabel permanentLabel;
permanentLabel.setText("permanent statusbar");
ui->statusbar->addPermanentWidget(permanentLabel);
progressBar1 = new QProgressBar;
progressBar1->setMaximumWidth(200);
progressBar1->setMinimum(5);
progressBar1->setMaximum(50);
progressBar1->setValue(ui->actExit->font().pointSize());
ui->statusbar->addWidget(progressBar1);
//在工具栏上添加自定义组件,默认状态下ui界面的一个工具栏叫ui->toolBar
spinFontSize = new QSpinBox;
spinFontSize->setMinimum(5);
spinFontSize->setMaximum(50);
spinFontSize->setValue(ui->textEdit->font().pointSize());
spinFontSize->setMinimumWidth(50);
ui->toolBar->addWidget(new QLabel("字体大小: "));
ui->toolBar->addWidget(spinFontSize);
ui->toolBar->addSeparator(); //添加分割条
ui->toolBar->addWidget(new QLabel(" 字体 "));
comboFont = new QFontComboBox;
comboFont->setMinimumWidth(150);
ui->toolBar->addWidget(comboFont);
setCentralWidget(ui->textEdit);
}
7.QAction和QMainWindow状态栏工具栏菜单栏
1). QAction
⭐️添加资源文件
添加QAction前,应先给项目添加需要的图片文件夹,即Resources/res.qrc
1⃣️首先应把需要的图片资源放到项目根目录中
2⃣️然后在项目文件中选择“new file or project”
3⃣️给资源添加prefix前缀,此处用/images
4⃣️添加资源文件
QAction
Action是一个不可见的界面元素,通常用于菜单项、工具栏按钮
Action的主要信号是trigger(),若想适用某个设置好的QAction对象,则需要将其信号trigger()和编写好的槽函数关联起来
关联方法:
一般直接右键对应的QAction对象,选择“转到槽”,再选择信号即可.如下图:
设计QAction对象时,还要考虑到点击效果,多次点击的状态,多次点击的有效效果等问题
2). QMainWindow状态栏工具栏菜单栏
在QMainWindow对象ui界面中添加工具栏,只需右键“添加工具栏”,状态栏同理,如下图
工具栏属性设置
QAction图标显示不正常/不显示
窗体布局
1⃣️Q:如何让窗体内的组件,随窗口的大小变化而变化?
A:对整个窗体使用布局(水平,垂直,栅格布局)
2⃣️如何初始化窗口?
在构造函数中使用resize()
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(QSize(480,320));
}
3⃣️如何固定窗口大小?
1)绝对的固定,无法改变
setFixedSize()
void QWidget::setFixedSize(const QSize &s);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(QSize(1080,720));
this->setFixedSize(this->width(),this->height());
}
2)最大最小值固定,允许改变一定范围
setMinimumSize(), setMaximumSize()
void QWindow::setMinimumSize(const QSize &size);
void QWindow::setMaximumSize(const QSize &size);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(QSize(800,400));
this->setMinimumSize(QSize(100,100));
this->setMaximumSize(QSize(1920,1080));
}