五、Qt中的常用类
1. QString 字符串类
QString是Qt中的字符串类,与C/C++不同的是,不再使用ASCII编码,而使用Unicode编码。因此一个字符不是8位的char,而是16位的QChar,这就是为什么之前一个汉字占用一个字符的原因。、
QString几乎向前兼容所有std::string的API。
部分常用函数如下:
// 数字 → QString
// 参数1:要转换的数字
// 参数2:进制
// 返回值:转换后的字符串
QString QString::number(long n, int base = 10) [static]
// 数字 → QString
// 参数1:要转换的数字
// 参数2:进制
// 返回值:转换后的字符串,支持链式调用
QString & QString::setNum(int n, int base = 10)
// QString → 数字
// 参数1:转换是否成功
// 参数2:进制
// 返回值:转换的结果,如果转换失败为0
int QString::toInt(bool * ok = 0, int base = 10) const
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
// Unicode
QString text = "你好あいうㅙㅖабв";
// 遍历
for(int i=0;i<text.count();i++)
{
// at效率更高,[]可以作为左值
qDebug() << text.at(i);
}
int a = 1;
// 数字 → QString
text = QString::number(a);
qDebug() << text;
a = 63;
QString s = QString::number(a, 16); // s == "3f"
QString t = QString::number(a, 16).toUpper(); // t == "3F"
// 数字 → QString
text.setNum(a).append("fklsdh");
qDebug() << text;
// QString → 数字
// 函数名称:to数据类型
text = "0";
bool result;
a = text.toInt(&result,10);
qDebug() << a;
qDebug() << result;
}
Dialog::~Dialog()
{
}
2. 容器类
Qt基于C++的容器,重新提供了更轻巧、更安全和更易于使用的新容器类。这些新的容器类可以使程序最终的可执行文件体积减小,同时这些容器类可以被多个线程直接读取,也兼容C++绝大多数API。
2.1 QList类
本例不光讲解容器类的使用,同时增加自定义C++类的代码。
创建一个C++类的操作步骤如下:
1. 在Qt Creator中选中项目名称,鼠标右键,点击“添加新文件”。
2. 在弹出的窗口中,按照下图所示进行操作。
3. 在弹出的窗口中输入类名后点击“下一步”。
4. 在项目管理界面,直接点击完成。
Qt的容器类都增加了Java风格迭代器,与C++的STL风格相比,只有语法上的不同。对应关系如下:
C++ STL 风格 | Java风格 |
---|---|
QList::const_iterator | QListIterator |
QList::iterator | QMutableListIterator |
#ifndef STUDENT_H
#define STUDENT_H
#include <QString>
class Student
{
public:
Student(QString,int,QString);
QString getName() const;
void setName(const QString &value);
int getAge() const;
void setAge(int value);
QString getMajor() const;
void setMajor(const QString &value);
private:
QString name;
int age;
QString major; // 专业
};
#endif // STUDENT_H
#include "student.h"
Student::Student(QString name,int age,QString major)
:name(name)
{
this->age = age;
this->major = major;
}
QString Student::getName() const
{
return name;
}
void Student::setName(const QString &value)
{
name = value;
}
int Student::getAge() const
{
return age;
}
void Student::setAge(int value)
{
age = value;
}
QString Student::getMajor() const
{
return major;
}
void Student::setMajor(const QString &value)
{
major = value;
}
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
#include <QList>
// 引入学生类
#include "student.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
QList<Student> class23061;
Student s1("李新宇",33,"光电");
Student s2("贾洪瑞",18,"电子");
Student s3("谢德政",22,"畜牧");
Student s4("陈凯",62,"光电");
Student s5("王俊杰",63,"通信");
Student s6("何凯",67,"保安");
// 增
class23061.append(s1);
class23061 << s2 << s4 << s5;
class23061.prepend(s6); // 前插
class23061.insert(1,s3); // 在第二个位置插入s3
// 删
class23061.removeAt(2); // 删除第三个
// class23061.removeAll(s4); // 删除所有相同元素
class23061.removeFirst(); // 删除第一个
class23061.removeLast(); // 删除最后一个
// class23061.removeOne(s4); // 删除相同元素的第一个
// 改
class23061.replace(1,s6); // 把第二个元素替换为s6
// 遍历
for(int i=0;i<class23061.size();i++)
{
Student s = class23061.at(i);
qDebug() << s.getName() << s.getAge() << s.getMajor();
}
// Java迭代器
QListIterator<Student> iter(class23061); // 创建迭代器对象
while(iter.hasNext()) // 后续有无元素
{
Student s = iter.next(); // 移动迭代器且取出元素
qDebug() << s.getName() << s.getAge() << s.getMajor();
}
}
Dialog::~Dialog()
{
}
2.2 QMap类
QMap也拥有Java风格迭代器:
C++ STL 风格 | Java风格 |
---|---|
QMap<K,V>::const_iterator | QMapIterator<K,V> |
QMap<K,V>::iterator | QMutableMapIterator<K,V> |
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
QMap<QString,int> map;
// 增加
map.insert("月薪",10000);
map.insert("年龄",20);
map.insert("身高",199);
map.insert("体重",100);
// 移除
// 返回值表示移除的键值对数量
map.remove("体重");
// 判断某个键在不在
if(map.contains("身高"))
qDebug() << "包含身高键";
else
qDebug() << "不包含身高键";
// 修改
map["身高"] = 188;
// 取出
int result = map.value("月薪",-1);
qDebug() << result;
// Java风格迭代器
QMutableMapIterator<QString,int> iter(map);
while(iter.hasNext())
{
iter.next(); // 向后移动
QString k = iter.key();
int v = iter.value();
qDebug() << k << v;
}
qDebug() << map;
}
Dialog::~Dialog()
{
}
3. Qt数据类型
3.1 跨平台类型
Qt是一种跨平台的开发框架,需要保证常见的基本数据类型在各平台具有统一的长度,Qt因此为了这些数据类型定义了类型符号。
Qt 数据类型 | 等效定义 | 字节数 |
---|---|---|
qint8 | signed char | 1 |
qint16 | signed short | 2 |
qint32 | signed int | 4 |
qint64 | long long int | 8 |
qlonglong | long long int | 8 |
quint8 | unsigned char | 1 |
quint16 | unsigned short | 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.2 统一数据类型 QVariant
QVariant 类是Qt常见数据类型的统一类型,可以完成与常见类型的相互转换。
后续有一些函数的参数或返回值使用此类型,因此可以支持很多类型的匹配。
QVariant value(3.14);
QString text = value.toString(); // “3.14”
qDebug() << text;
3.3 QStringList字符串列表
QStringList是一个字符串列表,几乎等同于QList。
4. 时间与日期处理(熟悉)
在Qt中使用QDate类处理日期,使用QTime类处理时间,使用QDateTime类同时处理日期和时间。
QDateTime类常用功能有:
// 返回1970-1-1 00:00:00到到现在的毫秒数(基于格林威治时间)
qint64 QDateTime::currentMSecsSinceEpoch() [static]
以下是一个生成随机数的例子:
qint64 time = QDateTime::currentMSecsSinceEpoch();
qDebug() << time;
// 把time作为种子
qsrand(time);
// 生成 1-45 随机数
int rand = qrand()%45+1;
qDebug() << rand;
以下是一个时间戳的例子:
qint64 time = QDateTime::currentMSecsSinceEpoch();
ui->setupUi(this);
qDebug() << QDateTime::currentMSecsSinceEpoch() - time;
// 基于当前时区,从系统中返回一个包含当前日期和时间的QDatetime对象
QDateTime QDateTime::currentDateTime() [static]
// 把QDateTime中的数据转换为固定格式的字符串
// 参数为格式
QString QDateTime::toString(const QString & format) const
以下是一个格式化日期和时间的例子:
// 拿到QDateTime对象,包含当前数据
QDateTime dt = QDateTime::currentDateTime();
// 转换为固定格式
QString text = dt.toString("yyyy-MM-dd hh:mm:ss");
qDebug() << text; // "2023-10-20 16:00:44"
text = dt.toString("yyyy年MM月dd日");
qDebug() << text; // "2023年10月20日"
相关组件:
5. QTimer定时器类(掌握)
QTimer是定时器类,用于设定一个倒计时或者周期性触发的效果。
QTimer的常用属性有:
● interval : int
如果是一次性的定时器,此属性表示倒计时时间;如果是周期性的定时器,此属性表示间隔时间。单位毫秒
● singleShot : bool
表示是否是一次性
● active : const bool
表示当前定时器是否正在运行
QTimer常用函数如下:
// 启动定时器,如果定时器已经在运行,调用此函数会停止定时器运行并重新运行
void QTimer::start() [slot]
// 停止定时器
void QTimer::stop() [slot]
// 定时器每次触发时发射的信号
void QTimer::timeout() [signal]
例子:电子表
–来自百度网盘超级会员V6的分享
QLcdNumber组件使用:
// 给QLcdNumber设置字符串内容
ui->lcdNumber->display("11:23:23");
注意定时器对象要设置为堆内存,不归ui指针管
对应代码👇:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QTimer> // 定时器
#include <QDateTime>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QTimer* timer; // 定时器对象
private slots:
// 定时器触发的槽函数
void timeoutSlot();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this); // 0
// 手动调用槽函数刷新时间
// timeoutSlot(); // 解决刚刚运行时显示0的问题
timer = new QTimer(this); // 创建定时器对象
timer->setSingleShot(false); // 设置为周期性
timer->setInterval(1000); // 设置间隔时间1000ms
connect(timer,SIGNAL(timeout()),this,SLOT(timeoutSlot()));
timer->start(); // 启动定时器
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::timeoutSlot()
{
// 获得当前时间
QDateTime dt = QDateTime::currentDateTime();
// 格式化
QString text = dt.toString("hh:mm:ss");
// 设置显示
ui->lcdNumber->display(text);
}