QT5——模版库、工具类及控件(上)

简介: QT5——模版库、工具类及控件

文章目录

qt模版库

字符串类

操作字符串

查询字符串数据

字符串的转换

容器类

QList类、QLinkedList类和QVector类

QList类

QLinkedList类

QVector类

Java风格迭代器遍历容器

STL风格迭代器遍历容器

QMap类和QHash类

QMap类

QHash类

Java风格迭代器遍历容器

STL风格迭代器遍历容器

QVariant类

算法及正则表达式

常用算法

基本的正则表达式

控件

按钮组(Buttons)

示例:

输入部件(Input Widgets)

QDateTime类

QTimer类

显示控件组(Display Widgets)

Graphics View

Text Browser

QQuickWidget

空间间隔组(Spaacers)

布局管理组(Layouts)

容器组(Containers)

Widget对应的QWidget类的用法

项目视图组(Item Views)

Table View与Table Widget的区别

项目控件组(Item Widgets)

树形控件实例


qt模版库

字符串类

相比于C++提供的两种字符串:C风格的char 字符串和字符串类string,qt提供的字符串类QString的功能更为强大。

QString类保存16位Unicode值,提供了丰富的操作、查询和转换等函数。该类还进行使用了隐式共享、高效的内存分配策略等多方面的优化。


操作字符串

  • QString提供了一个二元的“+”操作符用于组合两个字符串,并且提供了一个“+=”操作符用于将一个字符串追加到另一个字符串的末尾。
QString str1 = "Welcome";
str1 = str1 + "to you !";
QString str2 = "hello, ";
str2 += "World! ";


  • QString::append()函数具有与“+=”操作符同样的功能,实现在一个字符串的末尾追加另一个字符串,例如:
QString str1 = "Welcome ";
QString str2 = "to ";
str1.append(str2); //str1 = "Welcome to"
str1.append("you! "); //str1 = "Welcome to you! "


  • 组合字符串的另一个函数是QString::sprintf(),此函数支持的格式定义符和C++库中的函数sprintf()定义是一样的,例如:
QString str;
str.sprintf("%s", "Welcome "); // str = "Wlecome "
str.sprintf("%s", " to  you! "); //str = " to you! "
str.sprintf("%s %s", "Welcome ", "to you! "); // str = "Welcome to you! "


  • Qt还提供了另一种方便的字符串组合方式,使用QString::arg()函数,此函数的重载可以处理很多数据类型。此外,一些重载具有额外的参数对字段的宽度、数字基数或者浮点数精度进行控制。通常,相对于函数QString::sprintf(),函数QString::arg()是一个比较好的解决方案,因为它类型安全,完全支持Unicode,并且允许改变“%n”参数的顺序,例如:
QString str;
Str = QString("%1 was born in %2.").arg("John").arg(1998);//Str = "John was born in 1998"


其中,%1被替换成了“John”,%2被替换成了 “1998”。


  • QString也提供了一些其他组合字符串的方法,包括以下方式:
  • insert()函数:在源字符串特定位置插入另一个字符串。
  • prepend()函数:在源字符串开头插入另一个字符串。
  • replace()函数:用指定的字符串代替源字符串中的某些字符。
  • 很多时候,去掉一个字符串两端的空白(空白字符包括回车符“\n”、换行字符“\r”,制表符“\t”和空格字符“ ”)非常有用。
  • QString::trimmed()函数:移除字符串两端的空白字符。
  • QString::simplified()函数:移除字符串两端的空白字符,使用单个空格字符 “ ”代替字符串中出现的空白字符。
QString str = "  Welcome \t to \n you!    ";
str = str.trimmed(); // str = "Welcome \t to \n you!"
str = str.simplified(); //str = "Welcome to you!"


查询字符串数据

  • 函数QString::startsWith() 判断一个字符串是否以某个字符串开头。此函数具有两个参数,一个参数指定了一个字符串,第二个参数指定了是否大小写敏感(默认情况是大小写敏感的)。
QString str = "Welcome to you!";
str.startWith("Welcome", Qt::CaseSensitive); //返回true
str.startWith("to you", Qt::CaseSensitive); //返回false


  • 函数QString::endsWith()类似于QString::startsWith(),此函数判断一个字符串是否以某个字符串结尾。
  • 必将两个字符串也是经常使用到的功能,QString提供了以下几种比较手段:
  • operator<(const QString &):比较一个字符串是否小于另一个字符串,如果是返回true。
  • operator<=(const QString &):比较一个字符串是否小于等于另一个字符串,如果是返回true。
  • operator==(const QString &):比较一个字符串是否等于另一个字符串,如果是返回true。
  • operator>=(const QString &):比较一个字符串是否大于等于另一个字符串,如果是返回true。
  • localeAwareCompare(const QString &, const QString &):静态函数,比较前后两个字符串,如果前面字符串小于后面的字符串,则返回负整数;如果等于返回0;如果大于则返回正整数。(该函数的比较是基于本地字符集的,与平台相关)
  • compare(const QString &, const QString &, Qt::CaseSensitivity):该函数可以指定是否进行大小写的比较,而大小写的比较是完全基于Unicode编码值的。

字符串的转换

QString类提供了丰富的转换函数,可以将字符串转换为数值类型或者其他的字符编码集。


  • QString::toInt()函数将字符串转换为整型数值,类似还有toDouble()、toFloat()、toLong()、toLongLong()等等。
QString str = "125";
bool ok;
int hex = str.toInt(&ok, 16);//ok = true, hex = 293
int dev = str.toInt(&ok, 10);//ok = true, dev = 125


  • QString提供的字符编码集的转换函数会返回一个const char *类型版本的QByteArray,即构造函数QByteArray(const char *)构造的QByteArray对象。这个类具有一个字节数组,它既可以存储原始字节(raw bytes),也可以存储传统的以“\0”结尾的8位字符串。在Qt中,使用QByteArray比使用const char *更方便,且QByteArray也支持隐式共享,转换函数有以下几种:
  • toAscii():返回一个ASCII编码的8位字符串。
  • toLatin1():返回一个Latin-1(ISO8859-1)编码的8位字符串。
  • toUtf8():返回一个UTF-8编码的8位字符串。
  • toLocal8Bit():返回一个系统本地(locale)编码的8位字符串。
QString str = "Welcome to you!";
QByteArray ba = str.toAscii();
qDebug() << ba;
ba.append("Hello, World!");
qDebug() << ba.data();


容器类

qt提供了一组统一的基于模版的容器类。对比C++的标准模版库中的容器类,Qt的这些容器更轻量、更安全并且更容易使用。此外,Qt的容器类在速度、内存消耗和内联(inline)代码等方面进行了优化。

存储在Qt容器中的数据必须是可赋值的数据类型,也就是说,这种数据类型必须提供一个默认的构造函数、一个复制构造函数和一个赋值操作运算符。

这样的数据类型包含了通常使用的大多数数据类型,包括基本数据类型(如int、double等)和Qt的一些数据类型(如QString、QData、QTime等)。不过,Qt的QObject及其子类是不能干存储在容器中的(可以存储类指针)。


QList<QToolBar> list; //error
QList<QToolBar*> list; //success


Qt的容器类是可以嵌套的。例如:


QHash<QString, QList<double> > hash;


  • 其中,QHash的键类型为QString,值类型为QList。注意,在最后两个“>”符号之间要保留一个空格,否则编译器会错认成“>>”操作符。

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


  • java风格迭代器(java-style iterators)
  • STL风格的迭代器(STL-style iterators),能够同Qt和STL的通用算法一起使用,并且在效率上更胜一筹。

QList类、QLinkedList类和QVector类

经常使用的Qt容器类有QList、QLinkedList和QVector等。在开发一个较高性能需求的应用程序时,我们需要了解这些容器类的运行效率。下面列出了这几个类的时间复杂度比较:


容器类 查找 插入 头部添加 尾部添加

QList O(1) O(n) Amort O(1) Amort O(1)

QLinkedList O(n) O(1) O(1) O(1)

QVector O(1) O(n) O(n) Amort O(1)

QList类

QList是最常用到的容器类,它存储给定的数据类型T的一列数值。继承自QList类的子类有QItemSelection、QQueue、QSignalSpy及QStringList和QTestEventList。


QList不仅提供了可以在列表中进行追加的 QList::append() 和 QList::prepend() 函数,还提供了可以在列表中间完成插入操作的函数 QList::inseert() ,相对于任何其他的Qt容器类,为了可执行代码尽可能少,QList被高度优化。


QList维护了一个指针数组,该数组存储的指针指向QList 存储的列表项的内容。因此,QList 提供了基于下标的快速访问。


对于不同的数据类型,QList 采取不同的存储策略,存储策略有以下几种:


  • 如果T是一个指针类型或指针大小的基本类型(即所占字节数和基本类型所占字节数相同),QList会将数值直接存储在它的数组中。
  • 如果QList存储对象的指针,则该指针指向实际存储的对象。

例如:

#include <QDebug>
int main()
{
  //声明一个QList<QString>栈对象
  QList<QString> list;
  {
  QString str("This is a test string");
  list << str;//通过“<<”运算符将QString字符串存储到该列表中
  }//使用花括号进行作用域表明,此时QList<T>保存了对象的复制。
  qDebug() << list[0] << "How are you! ";
  return 0;
}


QLinkedList类

QLinkedList是一个链式列表,它以非连续的内存块存储数据。

QLinkedList 不能使用下标,只能使用迭代器访问它的数据。与QList相比,当对一个很大的列表项进行插入操作时,QLinkedList具有更高的效率。


QVector类

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


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


Java风格迭代器遍历容器

Java风格的迭代器同STL风格的迭代器相比,使用起来更简单方便,不过这也是以轻微的性能损耗为代价的。对于每一个容器类,Qt都提供了两种类型的Java风格迭代器数据类型,即只读访问和读写访问,其分类如下:


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

QList, QQueue QListIterator QMutableListIterator

QLinkedList QLinkedListIterator QMutableLinkedListIterator

QVector, QStack QVectorIterator QMutableVectorIterator

Java风格迭代器的迭代点(Java-style iterators point)位于列表项的中间,而不是直接指向某个列表项。因此,它的迭代点或者在第一个列表项的前面,或者在两个列表项之间,或者在最后一个列表项之后。

下面以QList为例,介绍Java风格的两种迭代器的用法。QLinkedList和QVector具有和QList相同的遍历接口。


  • 示例
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QList<int> list;
  list << 1 << 2 << 3 << 4 << 5;
  QListIterator<int> i(list);
  for(; i.hasNext();)
  qDebug() << i.next();
  return a.exec();
}

20200228112033980.png

上面使用的 i.hasNext()是对列表进行向后遍历的函数,而对列表进行向前遍历的函数有以下几种:


QListIterator<T>::toBack() :将迭代点移动到最后一个列表项的后面。
QListIterator<T>::hasPrevious() :检查当前迭代点之前是否具有列表项。
QListIterator<T>::previous() :返回前一个列表项的内容并将迭代点移动到前一个列表项之前。
此外:
toFront():移动迭代点到列表的前端(第一个列表项前面)
peekNext():返回下一个列表项,但不移动迭代点。
peekPrevious():返回前一个列表项,但不移动迭代点。
findNext():从当前迭代点开始向后查找指定的列表项,如果找到返回true,否则返回false。
findPrevious():与findNext()类似,不同的是它的方向是向前的,查找操作完成后的迭代点在匹配项的前面或整个列表的前端。


实现QList读写遍历方法:


#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QList<int> list;
  QMutableListIterator<int> i(list);
  for(int j = 0; j < 10; ++j)
  i.insert(j);
  for(i.toFront(); i.hasHext(); )
  qDebug() << i.next();
  for(i.toBack(); i.hasPrevious(); )
  {
  if(i.previous() % 2 == 0)
    i.remove();
  else
    i.setValue(i.peekNext() * 10);
  }
  for(i.toPront(); i.hasNext(); )
  qDebug() << i.next();
  return a.exec();
}

20200228113230857.png

STL风格迭代器遍历容器

对于每一个容器类,Qt都提供了两种类型的STL风格迭代器数据类型:


  • 提供只读访问
  • 提供读写访问

由于只读访问类型的迭代器的运行速度要比读写访问迭代器的运行速度快,所以应尽可能地使用只读类型的迭代器。STL风格迭代器的两种分类如下:

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

QList,QQueue QList::const_iterator QList::iterator

QLinkedList QLinkedList::const_iterator QLinkedList::iterator

QVector, QStack QVector::const_iterator QVector::iterator

STL风格迭代器的API是建立在指针操作的基础上的。例如“++”操作运算符移动迭代器到下一个选项(item),而“ * ”操作符返回迭代器指向的项。


示例:


#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QList<int> list;
  for(int j = 0; j< 10; j++)
  list.insert(list.end(), j);
  QList<int>::iterator i;
  for(i = list.begin(); i != list.end(); ++i)
  {
  qDebug() << (*i);
  *i = (*i) * 10;
  }
  QList<int>::const_iterator ci;
  for(ci = list.constBegin(); ci != list.constEnd(); ++ci)
  qDebug() << *ci;
  return a.exec();
}

20200228181117802.png

QMap类和QHash类

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


  • QHash具有比QMap更快的查找速度;
  • QHash以任意的顺序存储数据向,而QMap总是按照键Key的顺序存储数据。
  • QHash的键类型Key必须提供operator==() 和一个全局的qHash(Key) 函数,而QMap的键类型Key编写提供operator<()函数。

二者的时间复杂度比较如下:

容器类 键查找 – 插入 –

平均值 最坏情况 平均情况 最坏情况

QMap O(log n) O(log n) O(log n) O(log n)

QHash Amort.O(1) O(n) Amort.O(1) O(n)

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

QMap类

QMap<Key,T>提供了一个从类型为Key的键到类型为T的 值的映射。


通常,QMap存储的数据形式是一个键对应一个值,并且安装键Key的顺序存储数据。为了能够支持一键多值的情况,QMap提供了QMap<Key,T>::insertMulti() 和 QMap<Key,T>::values() 函数。存储一键多值的数据时,也可以使用QMultiMap<Key,T>容器,它集成自QMap。


QHash类

QHash<Key,T> 具有与QMap几乎完全相同的API,QHash维护着一张哈希表(Hash Table),哈希表的大小与QHash的数据项的数目相适应。


QHash以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,建议使用QHash作为存放数据的容器,QHash也可以存储一键多值形式的数据,它的子类QMultiHash<Key,T>实现一键多值的语义。


Java风格迭代器遍历容器

对于每一个容器类,Qt都提供了两种类型的Java风格迭代器数据类型:


  • 提供只读访问;
  • 提供读写访问;

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

QMap<Key,T> , QMultiMap<Key,T> QMapIterator<Key,T> QMutableMapIterator<Key,T>

QHash<Key,T>, QMultiHash<Key,T> QHashIterator<Key,T> QMutableHashIterator<Ket,T>

示例代码:


#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QMap<QString, QString> map;
  //想栈对象插入<城市,区号>对
  map.insert("beijing", "111");
  map.insert("shanghai", "021");
  map.insert("nanjing", "025");
  //创建一个只读迭代器
  QMapIterator<QString,QString> i(map);
  for(; i.hasNext(); )
  qDebug() << " " << i.key() <<" " <<i.next().value();
  //创建一个读写迭代器
  QMutableMapIterator<QString,QString> mi(map);
  if(mi.findNext("111"))
  mi.setValue("010");
  QMapIterator<QString,QString> modi(map);
  qDebug() << "修改后:";
  for(; modi.hasNext(); )
  qDebug() <<" " << modi.key() <<" " <<modi.next().value();
  return a.exec();
}

20200228204506655.png

STL风格迭代器遍历容器

对于每一个容器类,Qt都提供了两种类型的STL风格迭代器数据类型:


  • 提供只读访问;
  • 提供读写访问。

如下:

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

QMap<Key,T>, QMultiMap<Key,T> QMap<Key,T>::const_iterator QMap<Key,T>::iterator

QHash<Key,T>, QMultiHash<Key,T> QHash<Key,T>::const_iterator QHash<Key,T>::iterator

示例:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  QMap<QString, QString> map;
  //想栈对象插入<城市,区号>对
  map.insert("beijing", "111");
  map.insert("shanghai", "021");
  map.insert("nanjing", "025");
  //创建一个只读迭代器
  QMap<QString,QString>::const_iterator i;
  for(i = map.constBegin(); i != map.constEnd(); ++i)
  qDebug() << " " <<i.key() <<" " <<i.value();
  //创建一个读写迭代器
  QMap<QString,QString>::iterator mi;
  mi = map.find("beijing");
  if(mi != mi.end())
  mi.value() = "010";
  qDebug() << "修改后:";
  QMap<QString,QString>::const_iterator modi;
  for(modi = map.constBegin(); modi != map.constEnd(); ++modi)
  qDebug() << " " <<modi.key() <<" " <<modi.value();
  return a.exec();
}

20200228205551658.png


QVariant类

QVariant类类似于C++的联合(union)数据类型,它不仅能够保存很多Qt类型的值,包括QColor、QBrush、QFont、QPen、QRect、QString和QSize等,也能够存放Qt的容器类型的值。Qt的很多功能都是建立在QVarient基础上的,比如Qt的对象属性及数据库功能等。


示例:

新建Qt Widget项目,取消选择“创建界面”复选框,建好项目后在widget.cpp文件中编写以下代码:


#include "widget.h"
#include <QDebug>
#include <QVariant>
#include <QColor>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVariant v(709);
    qDebug() <<v.toInt();
    QVariant w("How are you! ");
    qDebug() << w.toString();
    QMap<QString, QVariant> map;
    map["int"] = 709; //输入整形
    map["double"] = 709.709; //输入浮点型
    map["string"] = "How are you!"; //输入字符串
    map["color"] = QColor(255, 0, 0); //输入QColor类型的值
    //调用相应的转换函数输出
    qDebug() << map["int"] <<map["int"].toInt();
    qDebug() << map["double"] << map["double"].toDouble();
    qDebug() << map["string"] << map["string"].toString();
    qDebug() << map["color"] << map["color"].value<QColor>();
    QStringList sl; //创建一个字符串列表
    sl << "A" << "B" << "C" << "D"; 
    QVariant slv(sl);   //将该列表保存到一个QVariant变量中
    if(slv.type() == QVariant::StringList)
    {
        QStringList list = slv.toStringList();
        for(int i = 0; i < list.size(); ++i)
        {
            qDebug() << list.at(i); //输出列表内容
        }
    }
}
Widget::~Widget()
{
}

20200228211417682.png

示例说明:


  • QVariant v(709):声明一个QVariant变量v,并且初始化为一个整数,此时变量v中包含一个整数变量。
  • qDebug() << v.toInt();调用QVariant::toInt()函数将变量中包含的内容转换成整数并输出。
  • if(slv.type() == QVariant::StringList):QVariant::type()函数返回存储在QVariant变量中的值的数据类型。QVariant::StringList是Qt定义的一个QVariant::type枚举类型的变量,其他常用的枚举类型变量如下:

变量 对应的类型 变量 对应的类型

QVariant::Invalid 无效类型 QVariant::Time QTime

QVariant::Region QRegion QVariant::Line QLine

QVariant::Bitmap QBitmap QVariant::Palette QPalette

QVariant::Bool bool QVariant::List QList

QVariant::QBrush QBrush QVariant::SizePolicy QSizePolicy

QVariant::Szie QSize QVariant::String QString

QVariant::Char QChar QVariant::Map QMap

QVariant::Color QColor QVariant::StringList QStringList

QVariant::Cursor Qcursor QVariant::Point QPoint

QVariant::Date QDate QVariant::Pen QPen

QVariant::DateTime QDateTime QVariant::Pixmap QPixmap

QVariant::Double double QVariant::Rect QRect

QVariant::Font QFont QVariant::Image QImage

QVariant::Icon QIcon QVariant::UserType 用户自定义类型



相关文章
|
1月前
|
计算机视觉 数据格式
使用opencv在Qt控件上播放mp4文件
使用opencv在Qt控件上播放mp4文件
34 2
|
2月前
|
算法 API C++
【Qt UI】QT 窗口/控件置顶方法详解
【Qt UI】QT 窗口/控件置顶方法详解
75 0
|
2月前
|
算法 前端开发 C++
【Qt UI相关】Qt设置窗体或控件的背景色透明
【Qt UI相关】Qt设置窗体或控件的背景色透明
30 0
|
1月前
|
开发框架 数据可视化 前端开发
【Qt 学习笔记】Qt控件概述
【Qt 学习笔记】Qt控件概述
25 0
|
1月前
|
图形学 Python 容器
【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)
【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)
53 0
|
1月前
|
编解码
qt中使用dll库的方法
qt中使用dll库的方法
18 2
|
1月前
|
存储
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
|
1月前
|
编译器
正点原子IMX6ULL-安装交叉编译器、编译tslib触摸屏库、编译arm环境qt源代码
正点原子IMX6ULL-安装交叉编译器、编译tslib触摸屏库、编译arm环境qt源代码
|
1月前
QT中edit控件限制输入数值以及进制转换方法
QT中edit控件限制输入数值以及进制转换方法
|
编译器 C语言 开发者
Qt Quick 常见控件与子控件布局规则
Qt Quick 常见控件与子控件布局规则
48 1

相关实验场景

更多

推荐镜像

更多