关闭
关闭
首页 > 嵌入式软件 > QT

 一、前言  “合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下”,上一章我们知道了如何使用Qt创建简单的示例程序,了解了最基本的Qt框架,在进一步学习Qt框架和消息机制前,我们应该对Qt本身有一个更细致的了解,这个了解就是Qt的模板库、工具类和控件。

回到顶部(go to top)

二、Qt的模板库、工具类和控件2.1 字符串类1、字符串的操作  我们了解字符串的操作就是要了解字符串主要有哪些操作符,Qt基于C++继承和强化了string的功能,结构类型为QString,QString提供了一个二元的“+”和“+=”操作符,其中“+=”操作符功能和append函数方法具有同样的功能,是现在一个字符串末尾追加另一个字符串,学习时可基于C++中String类进行比较。

1 QString str1="nihao";

2 QString str2="Qt";

3

4 str1+=str2; //str1="nihaoQt"

5 str1=str1+str2; //str1="nihaoQtQt"

6 str1.append(str2); //str1="nihaoQtQtQt"

7 str1.append("yes"); //str1="nihaoQtQtQtyes"

 Qt组合字符串的另一个函数楇 QString::sprintf(),此函数支持的格式定义符和C++库中的函数sprintf定义的一样。Qt还提供了另外一种方便的字符串组合方式,使用QString::arg()函数,此函数的重载可以处理多种数据类型,一些重载具有额外的参数对字段的宽度、数字基数或者浮点数精度进行控制。相对于sprintf来说,srg是一个比较好的解决方案,因为它类型安全,完全支持Unicode,并且允许改变"%n"参数的顺序。

1 QString str;

2 str=QString("%1 was born in %2 .").arg("Rimond").arg(1990);

3 //str="Rimond was born in 1990".

此外,QString也提供了一些其他组合字符串的方法

函数名称函数功能

insert()在原字符串特定的位置插入另一个字符串

prepend()在原字符串的开头插入另一个字符串

replace()用指定的字符串代替原字符串中的某些字符

为了解决特定场景比如去除一个字符串两端的空白(空白字符包括回车字符“\n”,换行字符“\r”,制表符“\t”和空格字符等),QString提供了特定的函数。

函数名称函数功能

trimmed() 移出字符串两端的空白字符

simplified()移除字符串两端的空白字符,使用单个空格字符“ ”代替字符串中出现的空白字符

1 QString str=" Hello \t QT \n ! ";

2 str=str.trimmed();

3

4 //str=" Hello \t to \n you! "

5 //如果使用str=str.simplified(),str的结果是“Hello Qt !”

2、查询字符串数据  查询字符串数据有多种样式。

(1) QString::startsWith()判断一个字符串是否以某个字符串开头。此函数具有两个参数,第一个参数指定了一个字符串,第二个参数指定是否大小写敏感(默认大小写敏感)。

1 QString str="Hello Qt!";

2 str.startsWith("Hello",Qt::CaseSensitive); //返回真

3 str.startsWith("Qt",Qt::caseSenstive); //返回假

(2) QString::endwith()类似于QString::startswith(),它用来判断一个字符串是否以某个字符串结尾。

(3) QString::contains()判断一个指定的字符串是否出现过。

1 QString str ="Hello QT!";

2 str.contains("QT",Qt::CaseSensitive); //返回真

(4) QString类还重载了多种用于比较的操作符,用法可参照C++ string类中重载的比较操作符。此外,QString类增加了两个特殊函数。

localeAwareCompare(const QString&,const QString&):静态函数,比较前后两个字符串,如果前面字符串小于后面字符串,则返回值为负整数;如果等于则返回0;如果大于则返回值为正整数,该函数用于比较基于本地字符集,而且楇平台相关的,通常该函数用于向用户显示一个有序的字符串列表。

compare(const QString&,const QString&::CaseSensitivity):该函数可以指定是否进行大小写的比较,而大小写的比较楇完全基于字符的Unicode编码值的,而且是非常快的,返回值类似于localeAwareCompare函数。

3、字符串的转换  由于Qt的跨平台型,可移植性等特点反映了其在字符串上的灵活性,QString类提供了丰富的转换函数,可以实现讲一个字符串转换为数值类型或者其他的字符编码集。

(1) QString::toInt()函数实现了将字符串转换为整型数值,类似的函数还有toDouble()、toFloat()、toLong()、toLongLong()等。

1 QString str="125";

2 bool ok;

3 int hex=str.toInt(&ok,16); //ok=true,hex=293

4 int dec=str.toInt(&ok,10); //ok=true,dec=125

可以看到上面的16和10分别代表了进制,ok用于传递一个地址,表示转换结果。

(2) QString提供的字符串编码集的转换函数将会返回一个const char*类型版本的QByteArry,即构造函数QByteArry(const char*)构造的QByteArry对象。QByteArry类具有一个字符数组,它既可以存储原始字节(raw bytes),也可以存储传统的以“\0”结尾的8位的字符串。在Qt中,使用QByteArry比使用const char*更为方便,且QByteArry也支持隐式共享,转换函数有以下几种。

函数名称函数功能

toAscii() 返回一个ASCII编码的8位字符串

toLatin1()返回一个Latin-1编码的8位字符串

toUtf8()返回一个utf-8编码的8位字符串(utf-8是ASCII码的超集,它支持整个Unicode字符集)

toLocal8Bit()返回一个系统本地编码的8位字符串

 1 #include

2 #include

3 #include

4 #include

5

6 int main(int argc, char *argv[])

7 {

8 QCoreApplication a(argc, argv);

9 QString str="Hello Qt!";

10 QByteArray ba=str.toLatin1();

11 qDebug() << ba;

12 ba.append("Hello,world!");

13 qDebug() << ba.data();

14 return a.exec();

15 }

 

运行结果如下

 

 

提示:Qt5中去除了toAscii()函数,改用toLatin1()函数就可了,再就是debug环境下别忘了添加qDebug的头文件。

qDebug类似于cout格式输出。

附加:NULL字符串和空(empty)字符串的区别

一个NULL字符串就是使用QString的默认构造函数或者使用(const char*)0作为参数的构造函数创建的QString字符串对象;而一个空字符串是一个大小为0的字符串。一个NULL字符串一定是一个空字符串,而一个空字符串未必是一个NULL字符串。

验证方式

1 QString().isNull(); //true

2 QString().isEmpty(); //true

3 QString("").isNull(); //false

4 QString("").isEmpty(); //true

2.2 容器类  同C++的标准模板库中的容器类作比较,Qt提供了一组通用的基于模板的容器类。这些容器更轻量、更安全并且更容易使用,同时还在速度、内存消耗和内联等方面进行了优化。

对于Qt容器中的存储数据类型也有要求,这些数据必须是可以赋值的数据类型,换句话说就是该数据类型必须有一个默认的构造函数(无参数构造函数)、一个复制构造函数(拷贝构造)和一个赋值操作符函数。

其实这样的数据类型包含了通常我们使用的大多数数据类型,比如基本的数据类型(int和double等)和Qt的一些数据类型(如QString、QDate、QTime等)。但是,Qt的QObject及其他的子类(如QWidget和Qdialog等)是不可以存储在容器中的。

1 QList list; //error

2 QList

上述代码中,第一种是错误的。因为这些类(QObject及其他的子类)没有复制构造函数和赋值构造函数。解决的办法就是使用指向这些类的指针来作为存储类型。

另外的一点就是Qt的容器类是可以嵌套的,这一点C++的STL也是可以做到的。

1 QHase

Qt的容器类为遍历其中的内容提供了以下两种方法:

(1)Java风格的迭代器

(2)STL风格的迭代器,能够同Qt和STL的通用算法一起使用,并且在效率上也略胜一筹。

下面我们将通过具体的容器类来具体的了解Qt容器类的功能和使用方法。

2.2.1 QList类、QLinkedList类和QVector类  首先我们来看一下这三种容器类的操作时间复杂度。

容器类查找(访问)插入头部添加尾部添加

QListO(1)O(n)Amort.O(1)Amort.O(1)

QLinkedListO(n)O(1)O(1)O(1)

QVectorO(1)O(n)O(n)Amort.O(1)

注:其中Amort.O(1)表示,如果仅完成一次操作,可能会有O(n)行为;但是如果完成多次操作(比如n次),平均结果将会是O(1)。

1、QList类

QList是我们会经常使用的容器类,它存储给定数据类型T的一列数值。继承自QList类的子类有QItemSelection、QQueue、QSignalSpy及QStringList和QTestEvenList。QList不仅提供了可以在列表进行追加的QList::append()和QList::prepend()函数,还提供了在列表中间完成插入操作的函数QList::insert()。相对于任何其他的Qt容器类,为了使可执行代码尽可能的少,QList被高度优化。

QList维护了一个指针数组,该数组存储的指针指向QList存储的列表项的内容。因此,QList提供了基于下标的快速访问。对于不同的数据类型,QList采用不同的存储策略,主要有以下几种。

(1)如果T是一个指针类型或者指针大小的基本类型(就是说该基本类型占有的字节数和指针类型占有的字节数相同),QList会将数值直接存储在它的数组中。

(2)如果QList存储对象的指针,则该指针指向实际存储的对象。

 

复制代码

 

1 #include

2 #include

3 #include

4

5 int main(int argc, char *argv[])

6 {

7 QCoreApplication a(argc, argv);

8 QList list;

9 //{}用来表示作用域

10 {

11 QString str("this is a test string");

12 list<

13 }

14 qDebug()<

15 return a.exec();

16 }

 

复制代码

 

 

 

其中list<

(2)QLinkedList类

QLinkedList是一个链式列表,它以非连续的内存块保存数据。QLinkedList不能使用下标,只能使用迭代器访问他的数据项。与QList相比,当对一个很大的列表进行插入操作时,QLinkedList具有更高的效率。

(3)QVector类

QVector在相邻的内存中存储给定数据类型T的一组数值。在一个QVector的前部或者中间位置进行插入操作的速度是很慢的,这是因为这样的操作将导致内存中大量的数据被移动,这事有QVector存储数据的方式决定的。

QVector既可以使用下标访问数据项,也可以使用迭代器访问数据项。继承自QVector类的子类有QPolygon、QPolygonF、QStack。

注:其实平常我们用QList就可以,它既可以是存储指向存储类型的指针,也可以对小的数据进行直接存储。

附:STL风格迭代器遍历容器

对于每一个容器类,Qt都提供了两种类型的STL风格迭代器数据类型:一种提供只读访问;另一种提供读写访问。由于只读类型的迭代器的运行速度要比读写迭代器的运行速度快,建议尽可能使用只读类型的迭代器。

容器类只读迭代器类读写迭代器类

QList,QQueueQList::const_itertorQList::itertor

QLinkedListQLinkedList::const_itertorQLinkedList::itertor

QVector,QStackQVector::const_itertorQVector::itertor

  

1 #include

2 #include

3 #include

4

5 int main(int argc, char *argv[])

6 {

7 QCoreApplication a(argc, argv);

8 QList list;

9 for(int j=0;j<10;j++)

10 list.insert(list.end(),j);

11 QList::iterator i;

12 for(i=list.begin();i!=list.end();i++)

13 {

14 printf("%d ",*i);

15 *i=(*i)*10;

16 }

17 QList::const_iterator ci;

18 for(ci=list.constBegin();ci!=list.constEnd();ci++)

19 printf("%d ",*ci);

20 return a.exec();

21 }

  

 

 

注:如果使用qDebug输出的话,我认为每次迭代都会生成一个qDebug的临时对象,并且自动添加换行,所以我改成了printf(偷懒),另外关于容器类使用方法可以参考C++ STL的使用方法。

2.2.2 QMap类和QHash类  QMap类和QHash类具有非常类似的功能,他们的差别仅在于:

1、QHash具有比QMap更快的查找速度

2、QHash以任意顺序存储数据项,而QMap总是按照Key顺序存储数据;

3、QHash的键类型Key必须提供operator==()和一个全局的qHash(Key)函数,而QMap的键类型Key必须提供operator<()函数。

QMap和QHash的时间复杂度比较

 

 

1、QMap类

QMap

2、QHash类

QHash

附:STL风格迭代器遍历容器

和上面说到的容器相同,Qt也提供了两种类型的STL风格迭代器数据类型。

容器类只读迭代器读写迭代器

QMap

QHase

  

1 #include

2 #include

3 #include

4 int main(int argc, char *argv[])

5 {

6 QCoreApplication a(argc, argv);

7 QMap

8 map.insert("lili","1990");

9 map.insert("wangli","1992");

10 map.insert("zhangli","1989");

11 QMap

12 for(i=map.constBegin();i!=map.constEnd();i++)

13 qDebug()<<" "<

14 QMap

15 mi=map.find("lili");

16 if(mi!=map.end())

17 mi.value()="1995";

18 QMap

19 for(modi=map.constBegin();modi!=map.constEnd();modi++)

20 qDebug()<<" "<

21 return a.exec();

22 }

  

 

 

好了,关于字符串类和容器类先说这么多,如有错误,欢迎指正。

 

no pains ,no gains. 给自己加油,为未来奋斗。

换一批

延伸阅读

[行业资讯] Qt5.3重磅登场:增强跨平台性与全新收费模式

Qt5.3重磅登场:增强跨平台性与全新收费模式

移动设备操作系统种类的不断增加,开发者在开发应用的时候需要针对不同的平台分别开发APP,这既增加了开发者投入的成本,又延缓了APP上架的时间。但是,开发者热衷于多个平......

关键字: Qt5.3 Digia Qt开发者大会

[猎聘集] 为什么在中国电子工程师的发展明显不如软件工程师方向?

为什么在中国电子工程师的发展明显不如软件工程师方向?

做了9年硬件电路设计,5年智能手机,4年医疗器械,看到这个问题,心情很复杂,自己喜爱的工作居然无奈的发展到了这个窘境。......

关键字:电子工程师 软件工程师

[新鲜事] 台积电用10nm生产A11 联发科又该头疼了!

台积电用10nm生产A11 联发科又该头疼了!

有分析师透露消息指苹果的A11处理器基本确定会采用台积电的10nm工艺生产,这意味着台积电的7nm工艺不会早于明年三季度,必然导致10nm工艺产能非常紧张。这对于寄望多款产品采用台积电的10nm工艺来增强芯片竞争力的联发科来说显然是一个非常......

关键字:台积电 A11处理器 联发科 10nm

[破谣言] 让我来告诉你,为什么AI不会产生“意识”

让我来告诉你,为什么AI不会产生“意识”

拥有自我意识和情感的超级人工智能到底会不会出现?说实话,这个话题都烂大街了。科学家、科技大佬、各国政要们争论得头破血流,我们也不可能知道答案。......

关键字:人工智能 意识

[新鲜事] 我国首株夜光植物培育成功:亮度达到星光水平

我国首株夜光植物培育成功:亮度达到星光水平

近日,我国云南的科学家团队在国内首次培育成功了夜光植物,科学家通过生物工程技术,将海洋发光微生物的基因导入到了本氏烟草植物细胞中,经过植物组织培养和筛选后,获得了该夜光植物,填补了我国有关技术的空白,为该技术在国内的进一步应用奠定了基础。......

关键字:夜光 植物亮度 首株

[新鲜事] 最好骑的小蓝车Bluegogo人去楼空,共享经济的弊端暴露无遗

最好骑的小蓝车Bluegogo人去楼空,共享经济的弊端暴露无遗

小蓝单车人去楼空 押金难退回遭用户投诉 ofo摩拜两强争霸之下,是众多共享单车小品牌的血流成河,3Vbike、酷奇、小鹿、小鸣、町町……都以各种方式倒下。......

关键字:Bluegogo 小蓝单车 押金

[新鲜事] 扎克伯格再次抛售大量股票 曾经希望捐赠99%的股份

扎克伯格再次抛售大量股票 曾经希望捐赠99%的股份

据国外媒体The Verge报道,近日有消息显示Facebook公司CEO马克&middot;扎克伯格再次抛售了大量公司股票,总价值为9500万美元。此前,扎克伯格曾经提出希望捐赠Facebook公司99%的股份,他也正在向这一目标......

关键字:扎克伯格 科技 Facebook
条评论

我 要 评 论

网友评论

大家都爱看

  • 华为的优势,就是自家的各种自研芯片

    CPU即中央处理器,是一块超大规模的集成电路,是一台计算机的运算核心和控制核心。它的功能主要是解释计算机指令以及处理计算机软件中的数据。

    2017-08-16
  • 你不知道Ryzen芯片有多火?来看看AMD的股票吧

    据外媒报道,美银美林认为,AMD最新的Ryzen芯片可能会引发一波销售浪潮,进而推动该股继续上涨。它认为AMD股票还有40%以上的上涨空间。

    2017-08-16
  • 国产芯片:厚积薄发,强势崛起

    关于国产芯片,是近几年才有崛起的势头,可是在几年之前,国产芯片还处于“沉睡”的状态,尤其是手机芯片,几乎大部分都依赖进口,而且国外的市场几乎被高通和联发科所垄断,也就展讯还在市场边…

    2017-08-16
  • 为了数据安全 大疆无人机增加隐私飞行功能

    大疆周一表示,在美国陆军因为“网络缺陷”而要求其成员停用大疆无人机后,这家中国无人机制造商将加强无人机的数据安全性。 大疆政策和法务副总裁布伦丹&middot…

    2017-08-15
  • Intel代工 展讯发布14nm SC9853I手机SoC

    SC9853I采用的Intel的14nm FinFET制程,架构为8核64位Airmont架构,主频1.8GHz,GPU为Mali-T820 MP2,号称面向799~1299元档次的手机。…

    2017-08-15