1. QString字符串类(掌握)
QString是Qt的字符串类,与C++的string相比,不再使用ASCII编码,QString使用的是Unicode编码。
QString中每个字符都是一个16位的QChar,而不是8位的char。
QString完全支持中文,但是由于不同的技术可能会采用不同的中文编码, 也有可能会遇到中文编码一致性的问题。
从此乱码是路人
Qt中对C++的类重写时,充分考虑到了C++程序员的编程习惯,因此QString几乎支持所有string的API,除此之外也会增加一些额外的函数。
// int → QString
// 参数1:要转换的原始数据
// 参数2:进制
// 返回值:转换后的新的QString对象
QString QString::number(int n, int base = 10)[static]
// QString -> int
// 参数1:转换成功还是失败,成功参数设置为true、失败设置为false
// 参数2:进制
// 返回值:转换后的int数据,转换失败返回0
int QString::toInt(bool * ok = 0, int base = 10) const
dialog.h
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this); QString str = "안녕하세요.";
qDebug() << str; ui->textBrowser->append(str); // int → QString
int a = 255;
str = QString::number(a);
qDebug() << str; // "255"
str = QString::number(a,2);//二进制
qDebug() << str; // "11111111" str = QString::number(a,16);
qDebug() << str; // "ff" // QString -> int
bool result = false;
str = "0";
qDebug() << str.toInt(&result); // 0
qDebug() << result; // true str = "你好";
qDebug() << str.toInt(&result); // 0
qDebug() << result; // false
}Dialog::~Dialog()
{
delete ui;
}
举例
QString str1 = "0"; // 合法的数字0
QString str2 = "你好"; // 非数字字符串
QString str3 = "123"; // 合法数字bool ok1, ok2, ok3;int num1 = str1.toInt(&ok1); // 转换成功,num1=0, ok1=true
int num2 = str2.toInt(&ok2); // 转换失败,num2=0, ok2=false
int num3 = str3.toInt(&ok3); // 转换成功,num3=123, ok3=trueqDebug() << "str1:" << num1 << ok1; // 输出: 0 true
qDebug() << "str2:" << num2 << ok2; // 输出: 0 false
qDebug() << "str3:" << num3 << ok3; // 输出: 123 true
当使用 toInt() 转换用户输入或外部数据时,必须检查 ok 参数:
QString userInput = ui->lineEdit->text();
bool ok;
int value = userInput.toInt(&ok);if (ok) {
// 转换成功,使用value
qDebug() << "输入的是有效整数:" << value;
} else {
// 转换失败,处理错误
qDebug() << "输入不是有效整数";
QMessageBox::warning(this, "错误", "请输入有效的整数");
}
不建议死记QString的API,因为数量多且都有示例代码,只需要把常用的关键词记住即可:
2. 容器类(掌握)
Qt重写了C++的STL中的容器类,相比较于C++的容器类,Qt的容器类更轻巧、更安全、更加的易于使用。因为Qt的容器类进行了速度和存储的优化,减少了可执行文件的生成体积,几乎全面兼容STL容器类API接口,线程是安全的,可以被多个线程所访问。
2.1 顺序容器—QList类
本次课程内容使用QList类存储Student元素,Student是自定义类型。在Qt项目中创建一个C++类的操作步骤如下:
- 在Qt Creator中,选中项目名称,鼠标右键点击添加新文件。
- 在弹出的窗口中按照下图所示,进行操作
3.在弹出的窗口中输入类名(大驼峰/帕斯卡)
4.在项目管理界面直接点击完成,可以看到新的文件已经创建成功。
student.h
#ifndef STUDENT_H
#define STUDENT_H#include <QString>
class Student
{
public:
Student(int,QString,QString);
~Student(); int getId() const;
void setId(int value); QString getName() const;
void setName(const QString &value); QString getMajor() const;
void setMajor(const QString &value);private:
int id; // 编号
QString name; // 姓名
QString major; // 专业};#endif // STUDENT_H
student.cpp
#include "student.h"Student::Student(int id, QString name, QString major):id(id)
{
this->name = name;//两种写法
this->major = major;
}Student::~Student()
{}
int Student::getId() const
{
return id;
}void Student::setId(int value)
{
id = value;
}
QString Student::getName() const
{
return name;
}void Student::setName(const QString &value)
{
name = value;
}
QString Student::getMajor() const
{
return major;
}void Student::setMajor(const QString &value)
{
major = value;
}
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>
#include "student.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECTpublic:
explicit Dialog(QWidget *parent = 0);
~Dialog();private:
Ui::Dialog *ui;
};#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);
// 创建QList对象
QList<Student> lis;
Student s1(1,"志浩","开挖掘机");
Student s2(2,"云龙","开意大利炮");
Student s3(3,"雨龙","美容美发");
Student s4(4,"文博","算命的");
Student s5(5,"昌文","开挖掘机炒菜"); // 向后插入元素(链式调用)
lis << s1 << s2 << s3 << s4; // 插入
lis.insert(1,s5); // 在第二个位置上插入s5 // 删除元素
lis.removeFirst(); // 删除第一个元素 lis.removeLast(); // 删除最后一个元素 // 编译报错,不支持只定义类型比较,如果想要实现此功能,需要将==运算符重载
// lis.removeOne(s3); // 删除所有相同元素的第一个元素 // lis.removeAll(s3); // 删除所有相同元素 lis.removeAt(1); // 删除第二个元素 // 普通遍历
for(int i = 0; i < lis.count(); i++)
{
// at函数在qt中执行效率比[] 高
// 只能在右值使用
Student s = lis.at(i);
qDebug() << s.getId() << s.getName() << s.getMajor();
} // C++迭代器遍历
for(QList<Student>::iterator iter = lis.begin(); iter != lis.end(); iter++)
{
Student s = *iter;
qDebug() << s.getId() << s.getName() << s.getMajor();
}
}Dialog::~Dialog()
{
delete ui;
}
2.2 关联容器—QMap类
重新实现了STL中的map类,QMap也兼容了map类的大部分API,也增加了一些自己的API。
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this); // 创建一个栈内存对象***
QMap<QString,QString>map; // 插入数据
map.insert("姓名","旭杰");
map.insert("年龄","18");
map.insert("地址","同住地球村");
map.insert("专业","物联网");
map.insert("爱好","睡觉"); // 如果容器内的元素支持qDebug输出,则容器给本身也支持输出
qDebug() << map;//打印所有键值对 // 删除
qDebug() << map.remove("专业"); // 1 返回的是删除的键值对的数量
qDebug() << map.remove("专业"); // 0 没有了 // 判断某个键值对是否存在
if(map.contains("籍贯"))
{
map["籍贯"] = "山东省";
} qDebug() << map; qDebug() << map.value("爱好","没有 没有"); // "睡觉"
qDebug() << map.value("喜好","没有 没有"); // "没有 没有" // C++迭代器遍历
for(QMap<QString,QString>::iterator i = map.begin();i != map.end();i++)
{
// 输出键值对
qDebug() << i.key() << i.value();
}}Dialog::~Dialog()
{
delete ui;
}
3. Qt数据类型(掌握)
3.1 跨平台数据类型
Qt是一个跨平台的开发框架,所以必须保证各个平台的数据类型的长度保持一致,因此Qt为常见的基本类型定义了新的类型符号。
在Qt的环境下,可以直接使用。
3.2 QVariant统一变量类
QVariant类型可以与Qt常见的数据类型完成相互的转换,因此此类型的函数具有类似多态的特点。
使用QVariant类型完成数据类型转换:
qint64 a = 123;
QVariant v(a);
QString str = v.toString(); // 将qint64数据转换为QStringqDebug() << str; // "123" v = str;int b = v.toInt(); // 转换为intqDebug() << b; // 123
4. 时间与日期处理(掌握)
Qt中使用QDate类处理日期,使用QTime处理时间,使用QDateTime处理时间和日期。以QDateTime为例进行讲解。
需要注意的是,QDateTime的数据来自于系统时间,所以修改系统时间会影响到QDateTime的数据。
常用函数:
// 返回自1970年1月1日00:00:00到现在的毫秒数
qint64 QDateTime::currentMSecsSinceEpoch()[static]
- 时间戳的作用,计算代码的运算时间。
qint64 start = QDateTime::currentMSecsSinceEpoch();
ui->setupUi(this);qDebug() << QDateTime::currentMSecsSinceEpoch() - start;
2. 时间戳的其他作用
可以使用时间戳作为随机数的种子。但是需要注意,计算机中都是伪随机。不是真正的随机数,计算机无法做到真正的随机数。
获取当前的时间和日期对象。
// 返回一个包含当前日期和时间的QDateTime的对象
QDateTime QDateTime::currentDateTime()[static]
// 格式化输出年月日、时分秒
QString QDateTime::toString(const QString & format) const
秒:ss
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
qint64 start = QDateTime::currentMSecsSinceEpoch();
ui->setupUi(this);
qDebug() << QDateTime::currentMSecsSinceEpoch() - start; // 使用时间戳作为随机数的种子
qsrand(start); // 生成随机数(生成101以内的随机数)
qDebug() << qrand() % 101; QDateTime dt = QDateTime::currentDateTime();
qDebug() << dt.toString("yyyy年MMMM月dddd日 hh时mm分ss秒");
}Dialog::~Dialog()
{
delete ui;
}
其他与日期和时间相关的组件:
5. QTimer定时器(重点)
QTimer类可以实现一个延时任务或者周期任务。
延时任务:微波炉定时功能
周期任务:闹钟,每天都响
使用定时器需要包含头文件#include<QTimer>,定时器继承自QObject。
常用属性:
- interval : int
时间间隔,单位毫秒。
- singleShot : bool
是否为一次性。true为延时任务、false为周期任务。
- active : const bool
当前定时器的运行状态
// 构造函数,堆区开辟
QTimer:: QTimer(QObject * parent = 0)
QLCDNumber 组件
显示出10:30:32 这样的时间
因为显示时间需要8位,所以需要将此属性改为8
// lcdNuber的显式函数
void display(const QString & s)[slot]
// 定时器触发时,发射的信号
void QTimer:: timeout()[signal]
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QTimer>
#include <QDateTime>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:
Ui::Dialog *ui;private:
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); timer = new QTimer(this); // 提前刷新
timeoutSlot();//不提前刷新会先显示原来的0,再显示时间 // 设置时间间隔
timer->setInterval(500); // 设置为周期任务(默认就是周期任务)
timer->setSingleShot(false); connect(timer,SIGNAL(timeout()),
this,SLOT(timeoutSlot())); // 启动定时器
timer->start();
}Dialog::~Dialog()
{
if(timer->isActive()) // 如果正在运行,则先关闭
{
timer->stop(); // 关闭定时器
} delete timer;
delete ui;
}void Dialog::timeoutSlot()
{
// 获取当前时间,转换:时:分:秒格式的QString字符串
QString str = QDateTime::currentDateTime().toString("hh:mm:ss");
ui->lcdNumber->display(str);
}