Qt5模板库、工具类及控件
1、字符串类
1.1、操作字符串
QString 类保存16 位Unicode 值,该类还进行了使用隐式共享(implicit sharing) 、高效的内存分配策略等多方面的优化。
QString strl ="Welcome"; // const char* 类型的ASCII 字符串,以"\0"结尾的C 类型字符串 QString : :fromAscii() 函数转换为Unicode 编码。
strl=strl+"to you! ";//strl=" Welcome to you! "
QString str2="Hello, ";
str2+="World! "; //str2="Hello,World! "
//QString: :append() 函数具有与"+="操作符同样的功能,实现在一个字符串的末尾追加另一个字符串。
QString strl ="Welcome";
QString str2 ="to ";
strl.append(str2); //strl=" Welcome to"
strl.append("you! ");//strl="Welcome to you! "
QString str;
str.sprintf("%s"," Welcome"); //str="Welcome"
str.sprintf("%s"," to you! "); //str="to you! "
str.sprintf("%s %s"," Welcome", "to you!"); //str=" Welcome to you!"
QString str;
str=QString("%1 was born in %2.").arg ("John").arg (1998); / / str="John was born in 1998."
insert() //在原字符串特定的位置插入另一个字符串。
prepend() //在原字符串的开头插入另一个字符串。
replace() //用指定的字符串代替原字符串中的某些字符。
QString::trimmed() //移除字符串两端的空白字符。
QString::simplified() //移除字符串两端的空白字符,使用单个空格字符”“代替字符串中出现的空白字符。
QString str=" Welcome \t to \n you! ";
str=str.trimmed(); //str=" Welcome \t to \n you!"
1.2 查询字符串数据
//判断一个字符串是否以某个字符串开头。
QString str="Welcome to you! ";
str.startsWith("Welcorne",Qt: :CaseSensitive); //返回true
str.startsWith("you",Qt::CaseSensitive); //返回false
QString::endsWithO() //判断一个字符串是否以某个字符串结尾。
//判断一个指定的字符串是否出现过
QString str=" Welcome to you! ";
str. contains ("Welcome", Qt:: CaseSensitive); //返回true
//比较两个字符串 返回true
operator<(const QString&): 比较一个字符串是否小于另一个字符串。 <= == >=可替代<
localeAwareCompare(const QString&,const QString&): //静态函数,比较前后两个字符串。小于返回负整数;等于则返回0; 大于返回正整数值。基于本地(locale) 字符集与平台相的。通常,该函数用于向用户显示一个有序的字符串列表。
compare(const QString&,const QString&,Qt::CaseSensitivity): //指定是否进行大小写的比较,基于字符的Unicode编码值。
1.3 字符串的转换
//字符串转换为数值类
// toDouble()、toFloat()、toLong() 、toLongLong()等。
QString str="l25"; //初始化一个"125" 的字符串
bool ok;
//第二个参数指定转换的基数。字符串"0x"开头,则基数为16; 字符串以"0"开头基数为8; 其他情况,基数10
int hex=str.toInt (&ok, 16) ; // ok=true, hex=293 将字符串转换为整型数值
int dec=str.toInt(&ok,10); //ok=true,dec=125
//字符编码集的转换函数 返回const char*类型版本的QByteArray,即构造函数QByteArray(const char*)构造的QByteArray 对象。QByteArray类具有字节数组,既可存储原始字节(raw bytes) , 也可存储传统的以"\O" 结尾的8 位的字符串。在Qt中,使用QByteArray 比使用const char*更方便,且QByteArray也支待隐式共享。
toAscii()// 返回ASCII编码的8位字符串。
toLatinl()// 返回一个Latin-1 (ISO8859-1) 编码的8位字符串。
toUtf8()//返回一个UTF-8 编码的8 位字符串(UTF-8是ASCII 码的超集,它支待整个Unicode 字符集)
toLocal8Bit()//返回一个系统本地(locale) 编码的8位字符串。
QString str=" Welcome to you! "; //初始化一个字符串对象
QByteArray ba=str.toAscii(); //将Unicode转换为ASCII 码的字符串,存储在ba中。
qDebug ()<<ba; // 使用qDebug()函数输出转换后的字符串(qDebug() 函数支持输出Qt 对象)。
ba.append("Hello, World! ");//
qDebug()<<ba.data() ;//输出最后结果
//一个NULL字符串一定是一个空字符串,而一个空字符串未必是一个NULL 字符串。
QString("").isNull();//结果为false
QString("").isEmpty();//结果为true
2、容器类
- 基于模板的容器类,比STL更轻量、更安全更容易使用。
- 在速度、内存消耗和内联(inline) 代码等方面进行了优化(较少的内联代码将缩减可执行程序的大小)。
数据必须是可赋值的数据类型(该数据类型必须提供一个默认的构造函数(不需要参数的构造函数)、一个复制构造函数和一个赋值操作运算符。)
Qt 的QObject 及其他的子类不能存储在容器中,因为这些类没有复制构造函数和赋值操作运算符。但可以存储其指针。
QList<QToolBar*> list;
QHash<QString,QList<double> > //保留空格
容器类遍历Java-style iterators与STL-style iterators,后者可与QT一起使用,且效率更高。
2.1 Qlist 类、Qlinkedlist 类和QVector 类
时间复杂度比较"Amort.0(1)" 表示,如果仅完成一次操作,可能会有O(n) 行为;但是如果完成多次操作(如n 次),平均结果将会是0(1) 。
Qlist 类
QList 存储给定数据类型T的一列数值。继承自QList类的子类有QitemSelection 、QQueue 、QSignalSpy 、QStringList 和QTestEventList
。在列表中追加QList::append()和Q list::prepend()
,在中间插入QList::insert()
。为了使可执行代码尽可能少,QList 被高度优化。提供下标快速访问
对千不同的数据类型, QList 采取不同的存储策略,
(1) 如果T 是一个指针类型或指针大小的基本类型(即该基本类型占有的字节数和指针类型占有的字节数相同), QList会将数值直接存储在它的数组中。
(2) 如果QList 存储对象的指针,则该指针指向实际存储的对象。
#include <QDebug>
int main(int argc,char *argv[])
{
QList<QString> list; //(a)声明了一个QList<QString>栈对象。
{
QString str("This is a test string");
list<<str; //将一个QString 字符串存储在该列表中
}
qDebug()<<list[0]<<"How are you!";
return 0;
}
QLinkedList 类
QLinkedList链式列表,它以非连续的内存块保存数据。不能使用下标,只能使用迭代器访问它的数据项,当对一个很大的列表进行插入操作时, QLinkedList 具有更高的效率。
QVector 类
QVector在相邻的内存中存储给定数据类型T的一组数值。在QVector 前部或者中间位置进行插入操作的速度是很慢,因为将导致内存中的大量数据被移动,这是由存储数据的方式决定的。
可以用下标访问或迭代器访问数据项,继承自QVector
类的子类有QPolygon 、QPolygonF 和QStack
。
java风格迭代与C++风格迭代
Java比STL使用更方便,但以轻微性能损耗为代价。
Qt提供只读迭代器类和读写迭代器类两种Java 风格迭代器数据类型。
迭代点位于列表项的中间,前后中间。
QList 只读遍历方法
#include <QCoreApplication>
#in~lude <QDebug>
int main(int argc, char *argv[))
(
QCoreApplication a(argc, argv);
QList<int> list;
list<<l<<2<<3<<4<<5;
QListIterator<int> i(list);//QList 只读遍历方法
for (; i.hasNext();) //检查当前迭代点之后是否有列表项
//next() 函数将会跳过下一个列表项(即迭代点将位千第一个列表项和第二个列表项之间),并返回它跳过的列表项的内容。
qDebug()<<i.next();
return a. exec() ;
}
QListlterator<T>: :toBack()
: 将迭代点移动到最后一个列表项的后面。
QListlterator<T>: :hasPrevious()
: 检查当前迭代点之前是否具有列表项。
QListlterator<T>::previous()
: 返回前一个列表项的内容并将迭代点移动到前一个列表项之前。
除此之外, QListlterator提供的其他函数还有如下几种。
toFront()
: 移动迭代点到列表的前端(第一个列表项的前面)。
peekNext()
: 返回下一个列表项,但不移动迭代点。
peekPrevious()
: 返回前一个列表项,但不移动迭代点。
findNext()
: 从当前迭代点开始向后查找指定的列表项,找到返回true, 迭代点位千匹配列表项的后面;没找到返回false,迭代点位千列表的后端(最后一个列表项的后面)。
findPrevious()
: 方向向前,查找操作完成后的迭代点在匹配项的前面或整个列表的前端。
读写迭代器QMutableListlterator除提供基本的遍历操作(与QListlterator 的操作相同)外,还提供了insert()插入操作函数、remove() 删除操作函数和修改数据函数等。
#include <QCoreApplication>
#include <QDebug>
int main(int argc,char *argv[])
{
QCoreApplication a(argc, argv);
QList<int> list; //创建一个空的列表list
QMutableListiterator<int> i(list); //创建上述列表的读写迭代器
for (int j=O; j<lO; ++j)
i.insert(j); //插入操作
for (i. to Front() ; i. hasNext () ;) // 将迭代器移动到列表前端,完成遍历
qDebug () <<i. next() ;
for(i.toBack();i.hasPrevious();) // 移动迭代器到列表后端,并遍历
{
if (i.previous ()%2==0)
1..remove();
else
i.setValue(i.peekNext()*lO);
}
for(i.toFront();i.hasNext();)
qDebug ()«i. next () ;
return a.exec();
}
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<int> list; //初始化一个空的QList<int>列表
for(int j=0;j<10;j++)
list.insert(list.end(),j); //(a)
QList<int>::iterator i;
//初始化一个QList<int>::iterator读写迭代器
for(i=list.begin();i!=list.end();++i) //(b)
{
qDebug()<<(*i);
*i=(*i)*10;
}
//初始化一个QList<int>:: const_iterator读写迭代器
QList<int>::const_iterator ci;
//在控制台输出列表的所有值
for(ci=list.constBegin();ci!=list.constEnd();++ci)
qDebug()<<*ci;
return a.exec();
}
QMap 类和Otlafill 类
QMap 类和QHash 类具有非常类似的功能,它们的差别仅在千:
• QHash 具有比QMap 更快的查找速度。
• QHash 以任意的顺序存储数据项,而QMap 总是按照键Key 的顺序存储数据。
• QHash 的键类型Key 必须提供operator==()和一个全局的qHash(Key) 函数,而QMap的键类型Key 必须提供operator<() 函数。
- QMap 类
QMap<Key, T>提供了一个从类型为Key 的键到类型为T 的值的映射。
通常, QMap 存储的数据形式是一个键对应一个值,并且按照键Key 的顺序存储数据。为了能够支持一键多值的情况,Map 提供了QMap<Key,T>: :insertMulti()和QMap<Key,T>: :values()函数。存储一键多值的数据时,也可以使用QMultiMap<Key,T>容器,它继承自QMap 。 - QHash 类
QHash<Key,T>维护着一张哈希表(Hash Table),哈希表的大小与QHash 的数据项的数目相适应。以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,建议使用QHash 作为存放数据的容器。QMultiHash<Key,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 () ;)
{
i .next();
qDebug () <<" "<<i. key () <<" "<<i. value ();
}
QMutableMapiterator<QString,QString> mi(map);
if (mi.findNext ("111"))
mi.setValue ("010");
QMapiterator<QString,QString> modi(map);
qDebug () <<" ";
for (; modi. hasNext () ;) //再次遍历井输出修改后的结果
{
modi.next();
qDebug () <<" "<<modi. key () <<" "<<modi. value ();
}
return a.exec();
hnclude <QCoreApplication>
hnclude <QDebug>
int main(int argc,char *argvf])
QCoreApplication a(argc, argv);
QMap<QString,QString> map;
map. insert ("bei扛ng","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>::i 七erator mi;
mi=map.find("beijing");
if (mi! =map. end())
mi. v·a.lue () ="010"; //(a)
QMap<QString;Qs_tring>: :const iterator modi;
qDebug () <<" ";
for (modi=map. constBegin ();modi! =map. constEnd (); ++modi)
qDebug()<<" "<<modi.key()<<" "<<modi.value();
return a.exec();
}
QVariant 类
QVariant 类类似千C++的联合(union) 数据类型,它不仅能保存很多Qt 类型的值,包括QColor 、QBrush 、QFont 、QPen 、QRect 、QString 和QSize 等,
#include "widget.h"
#include <QDebug>
#include <QVariant>
#include <QColor>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QVariant v(709); //(a)
qDebug()<<v.toInt(); //(b)
QVariant w("How are you! "); //(c)
qDebug()<<w.toString(); //(d)
QMap<QString,QVariant>map; //(e)
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>(); //(f)
QStringList sl; //创建一个字符串列表
sl<<"A"<<"B"<<"C"<<"D";
QVariant slv(sl); //将该列表保存在一个QVariant变量中
if(slv.type()==QVariant::StringList)//(g)
{
QStringList list=slv.toStringList();
for(int i=0;i<list.size();++i)
qDebug()<<list.at(i); //输出列表内容
}
}
Widget::~Widget()
{
}
算法及正则表达式
Qt 的<QtAlgorithms>
和<QtGlobal>
模块中提供的几种常用算法.使用正则表达式可以方便地完成处理字符串的一些操作,如验证、查找、替换和分割等。Qt 的QRegExp
类是正则表达式的表示类,它基千Perl 的正则表达式语言,完全支待Unicode 。
正则表达式由表达式(expressions) 、量词(quantifiers) 和断言(assertions) 组成。
字符集可以使用表达式如"[AEIOU]", 表示匹配所有的大写元音字母;使用"[AAEIOU]", 表示匹配所有非元音字母,即辅音字母;连续的字符集可以使用表达式如"[a-z] ", 表示匹配所有的小写英文字母。
量词说明表达式出现的次数,如"x(l,2]" 表示"x" 可以至少有一个,至多有两个。
" [A-Za-z_]+[A-Za-z_0-9]*"
其中,表达式中的"+“表示”[A-Za-z_]“至少出现一次,可以出现多次;“*”表示”[A-Za-z_ 0-9]"
可以出现零次或多次。
控件
按钮组(Buttons)
• Push Button: 按钮。
• Tool Button: 工具按钮。
• Radio Button: 单选按钮。
• Check Box: 复选框。
• Command Link Button: 命令链接按钮。
• Dialog Button Box: 对话框按钮盒。
输入部件组(Input Widgets)
• Combo Box: 组合框。
• Font Combo Box: 字体组合框。
• Line Edit: 行编辑框。
• Text Edit: 文本编辑框。
• Plain Text Edit: 纯文本编辑框。
• Spin Box: 数字显示框(自旋盒)。
• Double Spin Box: 双自旋盒。
• Time Edit: 时间编辑。
• Date Edit: 日期编辑。
• Date/Time Edit: 日期/时间编辑。
• Dial: 拨号。
• Horizontal Scroll Bar: 横向滚动条。
• Vertical Scroll Bar: 垂直滚动条。
• Horizontal Slider: 横向滑块。
• Vertical Slider: 垂直滑块。
• Key Sequence Edit: 按键序列编辑框。
QDateTime 类
Date/Time Edit 可以用来获得系统时间。通过QDateTime: :currentDateTime()来获取本地系统的时间和日期信息。可以通过date()和time()来返回datetime中的日期和时间部分,典型代码如下:
QLabel * datalabel =new QLabel();
QDa 七eTime *datatime=new QDateTime (QDateTime:: currentDateTime());
datalabel->setText(datatime->date ().toString ());
datalabel->show();
QTimer 定时器类
QTimer *time_clock=new QTimer(parent); //新建一个定时器。
connect(time_clock,SIGNAL(timeout()), this, SLOT (slottimedone ())); //连接这个定时器的信号和槽,利用定时器的timeout()
/*
定时器定时有两种方式: start(int time)和setSingleShot(true) 。其中, start(int time)表示每隔"time" 秒就会重启定时器,可以重复触发定时,利用stop()将定时器关掉;而setSingleShot(true)则是仅启动定时器一次。工程中常用的是前者.
*/
time_clock->start(2000);
显示控件组(Display Widgets)
• Label: 标签。
• Text Browser: 文本浏览器。
• Graphics View: 图形视图。
• Calendar Widget: 日历。
• LCD Number: 液晶数字。
• Progress Bar: 进度条。
• Horizontal Line: 水平线。
• Vertical Line: 垂直线。
• OpenGL Widget: 开放式图形库工具。
• QQuickWidget: 嵌入QML 工具。
Graphics View
对应于QGraphicsView 类提供了Qt5 的图形视图框架。
Text Browser
对应千QTextBrowser 类。QTextBrowser 类继承自QTextEdit, 而且仅是只读的,对里面的内容不能进行更改,但是相对千QTextEdit 来讲,它还具有链接文本的作用。QTextBrowser 的属性设置,可以设定QTextBrowser 是否允许外部链接夕是否为只读属性,外部链接的路径及链接的内容,是否可以进行撤销等操作。QTextBrowser 还提供了几种比较有用的槽(SLOTS), 即可以通过链接这几个槽来达到“翻页”效果。
QQuickWidget可以用它来嵌入QML 代码,但目前在QML 中尚不能嵌入其他非QML 窗口,因为QML 的渲染机制和QWidget 的是不一样的。
空间间隔组(Spacers)
• Horizontal Spacer: 水平间隔。
• Vertical Spacer: 垂直间隔。
布局管理组(Layouts)
• Vertical Layout: 垂直布局。
• Horizontal Layout: 横向(水平)布局。
• Grid Layout: 网格布局。
• Form Layout: 表单布局。
容器组(Containers)
• Group Box: 组框。
• Scroll Area: 滚动区域。
• Tool Box: 工具箱。
• Tab Widget: 标签小部件。
• Stacked Widget: 堆叠部件。
• Frame: 帧。
• Widget: 小部件。
• MDI Area: MDI 区域。
• Dock Widget: 停靠窗体部件。
• QAxWidget: 封装Flash 的ActiveX 控件。
Widget 对应QWidget 类的用法。Widget 是使用Qt 编写的图形用户界面(GUI)应用程序的基本生成块。每个GUI 组件,如按钮、标签或文本编辑器,都是一个Widget, 并可以放置在现有的用户界面中或作为单独的窗口显示。每种类型的组件都是由QWidget 的特殊子类提供的,而QWidget 又是QObject 的子类。
QWidget 是所有Qt GUI 界面类的基类,它接收鼠标、键盘及其他窗口事件,并在显示器上绘制自己。
通过传入QWidget 构造函数的参数(或者调用QWidget: :setWindowFlags()和QWidget::setParent()函数)可以指定一个窗口部件的窗口标识(window flags) 和父窗口部件。
窗口部件的窗口标识(window flags) 定义了窗口部件的窗口类型和窗口提示(hint) 。
窗口类型指定了窗口部件的窗口系统属性(window-system properties), 一个窗口部件只有一个窗口类型窗口提示定义了顶层窗口的外观,一个窗口可以有多个提示(提示能够进行按位或操作)。没有父窗口部件的Widget 对象是一个窗口,窗口通常具有一个窗口边框(frame) 和一个标题栏。QMainWindow 和所有的QDialog 对话框子类都是经常使用的窗口类型,而子窗口部件通常处在父窗口部件的内部,没有窗口边框和标题栏。
QWidget 窗口部件的构造函数为:QWidget(QWidget *parent=(),Qt::WindowFlags f=())其中,参数parent 指定了窗口部件的父窗口部件,如果parent=0(默认值),则新建的窗口部件将是一个窗口;否则,新建的窗口部件是parent 的子窗口部件(是否为一个窗口还需要由第二个参数决定)。如果新窗口部件不是一个窗口,则它会出现在父窗口部件的界面内部。参数
f 指定了新窗口部件的窗口标识,默认值是o, 即Qt::Widget 。
QWidget 定义的窗口类型为Qt::Window Flags 枚举类型,它们的可用性依赖千窗口管理器是否支待它们。
QWidget 不是一个抽象类,它可用作其他Widget 的容器,并很容易作为子类来创建定制Widget 。它经常用于创建放置其他Widget 的窗口。
对千QObject, 可使用父对象创建Widget 以表明其所属关系,这样可以确保删除不再使用的对象。使用Widget, 这些父子关系就有了更多的意义,每个子类都显示在其父级所拥有的屏幕区域内。也就是说,当删除窗口时,其包含的所有Widget 也都被自动删除。
项目视图组(Item Views)
• List View: 清单视图。
• Tree View: 树形视图。
• Table View: 表视图。
• Column View: 列视图。
模型/视图框架用于完成数据与表现的分离,这在Qt5 中称为InterView 框架,类似千常用的MVC 设计模式。模型(Model) 表示数据;视图(View) 是用户界面;控制(Controller) 定义了用户在界面上的操作。
• 模型:所有的模型都基千QAbstractltemModel 类,该类是抽象基类。
• 视图:所有的视图都从抽象基类QAbstractltemView 继承。
Inter View 框架提供了一些常见的模型类和视图类,如QStandardltemModel 、QDirModel、QStringListModel 、ProxyModel 和QColumnView 、QHeaderView 、QListView 、QTableView 、QTreeView 。其中,
QDirModel 可以通过树形方式显示某个目录下的所有子目录及其相关信息;
QProxyModel 用千将旧的Model 类型过渡到新的类型上;
QStandardltemModel 是用最简单的Grid方式显示Model 。
开发人员还可以从QAbstractListModel 、QAbstractProxyModel 、AbstractTableModel 继承出符合自己要求的Model 。
相对千使用现有的模型和视图, Qt 还提供了更为便捷的类用于处理常见的一些数据模型。它们将模型和视图合二为一,因此便千处理一些常规的数据类型。使用这些类型虽然简单方便,但也失去了模型/视图结构的灵活性,因此要根据具体情况来选择。
QTableWidget 继承自QTableView 。QSqlTableModel 能够与QTableView 绑定,但不能与QTableWidget 绑定。
视图与模型绑定时,模型必须使用new 创建, 会否则视图不能随着模型的改变而改变。
QSqlTableModel *model= new QSqlTableModel;
model->setTable("employee");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->removeColumn(O); //不显示ID
model->setHeaderData(O, Qt::Horizontal, tr("Name"));
model->setHeaderData(l, Qt::Horizontal, tr("Salary"));
QTableView *view= new QTableView;
view->setModel(model);
view->show();
项目控件组CItern Widgets)
• List Widget: 清单控件。
• Tree Widget: 树形控件。
• Table Widget: 表控件。