Linux环境下QT开发(三)——QT编程基础

Linux环境下QT开发(三)——QT编程基础

在上一篇文章中,我们完成了第一个程序——HelloWorld。在这篇文章中,我将介绍一些QT编程基础知识,让我们由此进入QT的世界!
本系列文章主要参考自《Qt 5.9 C++开发指南》,一本很适合初学者的书,此外,该文章还需要你有一定的C++基础哟
Qt5.9C++开发指南
本篇文章对应为该书中的第三章,但只介绍最基础部分,目前掌握这些就可以了

一、QT中的数据类型

QT为了统一不同平台上变量占用内存的大小,对一些常用变量进行了封装,在<QtGloabl>中都有定义,具体可参照下表

QT数据类型等效定义字节数
qint8signed char1
qint16signed short2
qint32signed int4
qint64long long int8
qlonglonglong long int8
quint8unsigned char1
quint16unsigned short2
quint32unsigned int4
quint64unsigned long long8
qulonglongunsigned long long int8
ucharunsigned char1
ushortunsigned short2
uintunsigned int4
ulongunsigned long8
qrealdouble8
qfloat2

另外,QT还对string类进行了封装,可以使用QString类。
当然,在QT中也可以使用C++本身的int之类的数据类型,但使用这些数据不但符合QT的代码风格,而且更可以保证跨平台通用性,那为什么不入乡随俗呢?

二、函数

<QtGlobal>中定义了一些常用函数,这些函数多以模板作为传入参数,也返回对应的模板类型

函数功能
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)若p1和p2近似相等,返回true
bool qFuzzyIsNull(double d)如果参数d约等于0,返回true
double qInf()返回无穷大的数
bool qIsFinite(double d)若d是一个有限的数,返回true
bool qIsInf(double d)若d是一个无限大的数,返回true
bool qIsNaN(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 qrand(uint seed)标准C++中srand()函数的线程安全型版本,使用种子seed对伪随机数序列初始化

三、容器类

QT的容器类比标准模板库(STL)中的容器类更轻巧、安全和易于使用。
此外,它们还是线程安全的,也就是说它们作为只读容器时可以被多个线程访问。

容器类是基于模板的类,如常用的QList<T>,T是一个具体类型,可以使int、float等简单类型,也可以是QString、QDate等类,但不能是QObject或任何其子类。T必须是一个可赋值的类型,即T必须提供一个缺省的构造函数,一个可复制的构造函数和一个赋值运算符。

总的来说就是普通数据类型都可以作为模板的具体类型来构建容器,具体QObject类是什么,哪些是它的子类,我们后面再说。
QT的容器类分为顺序容器和关联容器。

(一)顺序容器类

顺序容器类包括QList、QLinkedList、QVector、QStack和QQueue。

  1. QList
    常用函数
函数功能
insert()插入
replace()替换
removeAt()删除
move()移动
swap()交换
append()添加
prepend()添加
removeFirst()移除
removeLast()移除
isEmpty()判断是否为空
size()返回元素个数

QList还提供像数组一样的下标访问方式
例如:

QList<QString> list;
list<<"one"<<"two"<<"three";
QString str1=list[1];
QString str0=list.at(0);
  1. QLinkedList
    QLinkedList<T>除了不提供基于下标索引的数据项访问外,其他接口函数与QList基本相同
  2. QVector
    QVector支持下标访问,性能比QList更高
  3. QStack
    QStack<T>是提供类似于队列先入先出(FIFO)操作的容器类。enqueue()dequeue()是主要的操作函数。
    例如:
QQueue<int> queue;
queue.enqueue(10);
queue.enqueue(20);
while(!queue.isEmpty())
	cout<<queue.dequeue()<<endl;
结果:1020

(二)关联容器类

关联容器类包括QMap、QMultiMap、QHash、QMultiHash、QSet。

  1. QSet
    例如:
QSet<QString> set;
set<<"dog"<<"cat";
if(!set.contains("mouse")
	set<<"mouse";
  1. QMap
    QMap<Key,T>提供一个字典(关联数组),一个键映射到一个值。
    例如:
QMap<QString,int> map;
map["one"]=1;
map["two"]=2;
map.insert("three",3);
map.remove("two");
int num1 =map["one"];
int num2 =map.value("two");

如果在映射表中没有找到指定的键,会返回一个缺省的构造值。使用value()函数查找时,还可以指定一个缺省值

int num = map.value("my_num",10);
  1. QMultiMap
    QMultiMap是QMap的子类,是用于处理多值映射的便利类。QMap正常情况下不允许多值映射,除非使用QMap::insertMulti()添加键值对。
    QMultiMap::insert()等效于QMap::insertMulti(),QMultiMap::replace()等效于QMap::insert()
    例如:
QMultiMap<QString,int> map1,map2,map3;
map1.insert("num",100);
map1.insert("num",200);
map2.insert("num",300);
map3=map1+map2; //map3.size()==3

QMultiMap不提供"[ ]"操作符,使用value()函数访问最新插入的键的单个值。如果要获取一个键对应的所有值,使用values()函数,返回值是QList<T>类型。
例如:

QList<int> values =map.values("num");
for(int i=0;i<values.size();i++)
	cout<<values.at(i)<<endl;
  1. QHash
    QHash<Key,T>和QMap功能和用法相似,但QMap的键必须提供<运算符,QHash的键必须提供==运算符和一个名称为qHash()的全局散列函数。
  2. QMultiHash
    与QMultiMap相似

四、容器类的迭代

QT有两种迭代器类:Java类型的迭代器和STL类型的迭代器。
Java类型的迭代器更易于使用,且提供一些高级功能,而STL类型的迭代器效率更高。

(一)Java类型的迭代器

容器类只读迭代器读写迭代器
QList<T>,QQueue<T>QListIterator<T>QMutableListIterator<T>
QLinkedList<T>QLinkedListIterator<T>QMutableLinkedListeIterator<T>
QVevtor<T>,QStack<T>QVectorIterator<T>QMutableVectorIterator<T>
QSet<T>QSetIterator<T>QSetIterator<T>
QMap<Key,T>,QMultiMap<Key,T>QMapIterator<Key,T>QMutableMapIterator<Key,T>
QHash<Key,T>,QMultiHash<Key,T>QHashIterator<Key,T>QMutableHashIterator<Key,T>
  1. 顺序容器类的迭代器使用
    Java类型迭代器的指针不是指向一个数据项,而是在数据项之间。
    QListIterator<T>为例说明顺序容器类的迭代器常用方法
函数名功能
void toFront()迭代器移动到列表的最前面(第一个数据项之前)
void toBack()迭代器移动到列表的最后面(最后一个数据项之后)
bool hasNext()如果迭代器不是位于列表最后位置,返回true
const T &next()返回下一个数据项,并且迭代器后移一个位置
const T &peekNext()返回下一个数据项,但是不移动迭代器位置
bool hasPrevious()如果迭代器不是位于列表的最前面,返回true
const T &previous()返回前一个数据项,并且迭代器前移一个位置
const T &peekPrevious()返回前一个数据项,但是不已的迭代器指针

例如:

QList<int> list;
list<<1<<2<<3<<4<<5;
QMutableListIterator<int> i(list);
while(i.hasNext()){
	if(i.next()%2!=0)
		i.remove();
}

remove()函数移除next()函数刚刚跳过的一个数据项,不会使迭代器失效。
setValue()函数可以改变数据项的值。
2. 关联容器类的迭代器使用
关联容器类迭代器具有和上表一样的函数,主要是增加了key()和value()函数用于获取刚刚跳过的数据项的键和值。
在多值容器类里遍历,可以使用findNext()或findPrevious()查找下一个或上一个值,例如:

while(i.findNext("USA"))
	i.remove();

(二)STL类型迭代器

与Java类型迭代器不同,STL类型迭代器直接指向数据项。

  1. 顺序容器类的迭代器
容器类只读迭代器读写迭代器
QList<T>,QQueue<T>QList<T>::const_iteratorQList<T>::iterator
QLinkedList<T>QLinkedList<T>::const_iteratorQLinkedList<T>::iterator
QVevtor<T>,QStack<T>QVector<T>::const_iteratorQVector<T>::iterator
QSet<T>QSet<T>::const_iteratorQSet<T>::iterator
QMap<Key,T>,QMultiMap<Key,T>QMap<Key,T>::const_iteratorQMap<Key,T>::iterator
QHash<Key,T>,QMultiHash<Key,T>QHash<Key,T>::const_iteratorQHash<Key,T>::iterator

例如:

QList<QString> list;
list <<"A"<<"B"<<"C"<<"D";
QList<QString>::const_iterator i;
for(i=list.constBegin();i!=list.constEnd();i++)
	qDebug()<<*i;

constBegin()和constEnd()用于只读迭代器,表示其实和结束位置。

  1. 关联容器类的迭代器
    如果想返回键,使用key()函数,对应的,用value()函数返回一个项的值。
  2. QT很多函数返回值为QList或QStringList,但因为QT使用了隐式共享,所以并不费事。隐式共享简单的就是只读的时候共享内存,修改的时候再拷贝一份新的。
    因为有隐式共享,所以当有一个迭代器在操作容器变量时,不要复制这个容器变量。

五、QT宏定义之foreach

QT有很多宏定义,但这里只介绍这个foreach。
foreach(变量,容器)
例如:

QLinkedList<QString> list;
...
QString str;
foreach(str,list)
	qDebug()<<str;

foreach也可以使用大括号,使语句更复杂
对于QMap和QHash,foreach会自动访问键值对里得值,例如:

foreach(str,map.keys())
	qDebug()<<str<<":"<<map.value(str);

对于多值映射,可以使用双重foreach
请注意:foreach不能修改原来容器中的数据项

六、总结

好啦,看到这里希望你能学会这些基础知识,这些基础知识就能满足很多开发需求了,你已经不再是一个QT小白了。
我辛苦的搬运了一天书上的内容,才有了这篇文章,哈哈!当初学QT的时候我都没那么认真,不过这样做还是很值得的,现在为了写博客也为了兴趣想好好学一学,很有收获了。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CrystalGabrielle

喜欢就投喂一下吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值