其他分享
首页 > 其他分享> > QT5——模版库、工具类及控件

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

作者:互联网

文章目录


qt模版库

字符串类

相比于C++提供的两种字符串:C风格的char 字符串和字符串类string,qt提供的字符串类QString的功能更为强大。
QString类保存16位Unicode值,提供了丰富的操作、查询和转换等函数。该类还进行使用了隐式共享、高效的内存分配策略等多方面的优化。

操作字符串

QString str1 = "Welcome";
str1 = str1 + "to you !";
QString str2 = "hello, ";
str2 += "World! ";
QString str1 = "Welcome ";
QString str2 = "to ";
str1.append(str2); //str1 = "Welcome to"
str1.append("you! "); //str1 = "Welcome to you! "
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! "
QString str;
Str = QString("%1 was born in %2.").arg("John").arg(1998);//Str = "John was born in 1998"

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

QString str = "  Welcome \t to \n you!    ";
str = str.trimmed(); // str = "Welcome \t to \n you!"
str = str.simplified(); //str = "Welcome to you!"

查询字符串数据

QString str = "Welcome to you!";
str.startWith("Welcome", Qt::CaseSensitive); //返回true
str.startWith("to you", Qt::CaseSensitive); //返回false

字符串的转换

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

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 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;

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

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 采取不同的存储策略,存储策略有以下几种:

#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();
}

在这里插入图片描述上面使用的 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();
}

在这里插入图片描述

STL风格迭代器遍历容器

对于每一个容器类,Qt都提供了两种类型的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();
}

在这里插入图片描述

QMap类和QHash类

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

容器类 键查找 插入
平均值 最坏情况 平均情况 最坏情况
QMap O(log n) O(log n) O(log n) O(log n)
QHash Amort.O(1) O(n) Amort.O(1) O(n)

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();
}

在这里插入图片描述

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();
}

在这里插入图片描述

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()
{

}

在这里插入图片描述
示例说明:

变量 对应的类型 变量 对应的类型
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 用户自定义类型

算法及正则表达式

首先介绍Qt的 和 模块中几种常用算法,然后再介绍基本的正则表达式。

常用算法

#include "widget.h"
#include <QApplication>
#include <QDebug>


int main(int argc, char *argv[])
{
	QApplication a0(argc, argv);

    double a = -19.3, b = 9.7;
    double c = qAbs(a);//返回a的绝对值
    double max = qMax(b, c);//返回两个数值中最大值
    int bn = qRound(b);//返回一个与浮点数最接近的整数值。
    int cn = qRound(c);

    qDebug() << "a = " << a;
    qDebug() << "b = " << b;
    qDebug() << "c = qAbs(a) = " << c;
    qDebug() << "qMax(b,c)" << max;
    qDebug() << "bn = qRound(b) = " << bn;
    qDebug() << "cn = qRound(c) = " << cn;

    qSwap(bn, cn);//交换两个数的值
    qDebug() <<"qSwap(bn, cn) : " << "bn = " << bn << ", cn = " << cn;

    return a0.exec();
}

在这里插入图片描述

基本的正则表达式

使用正则表达式可以方便地完成处理字符串的一些操作,如验证、查找、替换和分割等。Qt的QRegExp类是正则表达式的表示类,它基于Perl的正则表达式语言,完全支持Unicode。

正则表达式由表达式(expressions)、量词(quantifiers)和断言(assertions)组成。

在计算机语言中,标识符通常要求以字母或下划线开头,后面可以是字母、数字和下划线。满足条件的标识符表示为:

" [A-Za-z_]+[A-Za-z_0-9]* "

其中,表达式中的“+”表示“[A-Za-z]”至少出现一次,可以出现多次;“ * ”表示“[A-Za-z_0-9]”可以出现0次或者多次。

量词 含义 量词 含义
E? 匹配0次或1次 E[n,] 至少匹配n次
E+ 匹配1次或者多次 E[,m] 最多匹配m次
E* 匹配0次或多次 E[n,m] 至少匹配n次,最多匹配m次
E[n] 匹配n次
符号 含义 符号 含义
^ 表示在字符串开头进行匹配 \B 非单词边界
$ 表示在字符串结尾进行匹配 (?=E) 表示表达式后缀紧随E才匹配
\b 单词边界 (?!E) 表示表达式后不跟随E才匹配

控件

本节简单介绍几个常用的控件,以便对Qt的控件有一个初步认识。

按钮组(Buttons)

按钮组如图所示:
在这里插入图片描述具体如下 :

示例:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H

#include "widget.h"
#include <qapplication.h>
#include <qpushbutton.h>
#include <qfont.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setMinimumSize(200, 120);
    setMaximumSize(200, 120);
    QPushButton *quit = new QPushButton("Quit", this);
    quit->setGeometry(62, 40, 75, 30);
    quit->setFont(QFont("Times", 18, QFont::Bold));
    connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}

Widget::~Widget()
{

}

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.setGeometry(100, 100, 200, 120);
    w.show();

    return a.exec();
}

输入部件(Input Widgets)

输入部件(Input Widgets)如下图:
在这里插入图片描述

QDateTime类

Date/Time Edit对应于QDateTime类,在Qt5中可以使用它获得系统时间。通过QDateTime::currentDateTime()来获取本地系统的时间和日期信息。可以通过date()和time()来返回datetime中的日期和时间部分。典型代码如下:


    QLabel *datalbel = new QLabel();
    QDateTime *datatime = new QDateTime(QDateTime::currentDateTime());
    datalbel->setText(datatime->date().toString());
    datalbel->show();

在这里插入图片描述

QTimer类

定时器(QTimer)的使用非常简单,只需要以下几个步骤就可以完成定时器的应用。

QTimer *timer_clock = new QTimer(parent);
connect(timer_clock, SIGNAL(timeout()), this, SLOT(slottimedone());

即定时时间一刀就会发生timeout()信号,从而触发slottimedone()槽去完成某件事情。

time_clock->start(2000);

显示控件组(Display Widgets)

显示控件组(Display Widgets)如下图所示:
在这里插入图片描述

Graphics View

Graphics View 对应于QGraphicsView类,提供了Qt5的图像视图框架。

Text Browser

Text Browser 对应于QTextBrowser类,QTextBrowser类继承自QTextEdit,而且仅是只读的,对里面的内容并不能继续更改,但是相对于QTextEdit来讲,它还具有链接文本的作用。


modified : const bool //通过布尔值来说明内容是否被修改
openExternalLinks : bool
openLinks : bool
readOnly : const bool
searchPaths : QStringList
source : QUrl
undoRedoEnabled : const bool

通过以上属性设置,可以设定QTextBrowser是否允许外部链接,是否为只读属性,外部链接的路径及链接内容,是否可以进行撤销等操作。

QTextBrowser还提供了几种比较有用的槽函数。

virtual void backward();//上一页
virtual void forward();//下一页
virtual void home(); //主页

可以通过链接这几个槽函数来达到“翻页”的效果。

QQuickWidget

QQuickWidget是Qt5.3发布的一个组件,传统的QWidget程序可以用它来嵌入QML代码,为Qt开发者将桌面应用迁移到Qt Quick提供了方便,但目前QML中尚不能嵌入其他非QML窗口,因为QML的渲染机制和QWidget是不一样的。

空间间隔组(Spaacers)

在这里插入图片描述

布局管理组(Layouts)

在这里插入图片描述

容器组(Containers)

在这里插入图片描述

Widget对应的QWidget类的用法

Widget是使用Qt编写的图像用户界面(GUI)应用程序的基本生成块。每个GUI组件,如按钮、标签或文本编辑器,都是一个Widget,并可以放置在现有的用户界面中或作为单独的窗口显示。每种类型的组件都是由QWidget的特殊子类提供的,而QWidget自身又是QObject的子类。

QWidget是所以QtGUI界面类的基类,它接收鼠标、键盘及其他窗口事件,并在显示器上绘制自己。

通过传入QWidget构造函数的参数(或者调用QWidget::setWindowFlags() 和 QWidget::setParent() 函数)可以指定一个窗口部件的窗口标识(window flag)和父窗口部件。

窗口部件的窗口标识(window flag)定义了窗口部件的窗口类型和窗口提示(hint)。窗口类型指定了窗口部件的窗口系统属性(window-system properties),一个窗口部件只能有一个窗口类型,窗口提示定义了顶层窗口的外观,一个窗口可以由多个提示。

没有父窗口部件的Widget对象是一个窗口,窗口通常具有一个窗口边框(frame)和一个标题栏。而子窗口部件通常处在父窗口部件的内部,没有窗口边框和标题栏。

QWidget窗口部件的构造函数为:

QWidget(QWidget *parent = 0, Qt::WindowFlags f = 0);
/*
parent:指定窗口部件的父窗口部件。如果为0则新建窗口部件蒋帅一个窗口。否则新建窗口将会出现在父窗口部件的界面内部。
f:指定了新窗口的窗口标识。默认是0,及Qt::Widget.
*/

示例:

 	QWidget *window = new QWidget();
    window->resize(320, 240);
    window->show();
    QPushButton *button = new QPushButton(QObject::tr("Press me"), window);
    button->move(100, 100);
    button->show();

在这里插入图片描述

 QWidget *window = new QWidget();
    //新建label进行布局
    QLabel *label = new QLabel(QObject::tr("Name:"));
    QLineEdit *lineEdit = new QLineEdit();
    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(label);
    layout->addWidget(lineEdit);
    window->setLayout(layout);

    window->resize(320, 240);
    window->show();
    QPushButton *button = new QPushButton(QObject::tr("Press me"), window);
    button->move(20, 20);
    button->show();

在这里插入图片描述

	QWidget *window = new QWidget();
    QLabel *queryLabel = new QLabel();
    QLineEdit *queryEdit = new QLineEdit();
    QTableView *resultView = new QTableView();
    QHBoxLayout *queryLayout = new QHBoxLayout();

    queryLayout->addWidget(queryLabel);
    queryLayout->addWidget(queryEdit);

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->addLayout(queryLayout);
    mainLayout->addWidget(resultView);
    window->setLayout(mainLayout);

    window->show();

在这里插入图片描述

项目视图组(Item Views)

在这里插入图片描述

Table View与Table Widget的区别

具体如下表:

区别点 QTableView QTableWidget
继承关系 QTableWidget集成子QTableView
使用数据模型setModel 可以使用setModel设置数据模型 setModel是私有函数,不能使用该函数设置数据模型
显示复选框setCheckState 没有函数实现复选框 QTableWidgetItem类中的setCheckState(Qt::Checked):可以设置复选框。
与QSqlTableModel 绑定 QTableView能与QSqlTableModel绑定 QTableWidget不能与QSqlTableModel绑定

Qt5中引入了模型/视图框架用于完成数据与表现的分离,这在Qt5中成为InterView框架,类似于常用的MVC设计模式。

MVC设计模式是起源于Smalltalk语言的一种与用户界面相关的设计模式。MVC包括三个元素:模型(model)表示数据;视图(view)表示用户界面;控制(controller)定义了用户在界面上的操作。同使用MVC模式,有效地分离了数据和用户界面,使得设计更为灵活,更能适应变化。

示例:

    QSqlTableModel *model = new QSqlTableModel();
    model->setTable("employee");
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();
    model->removeColumn(0);
    model->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("Salary"));
    QTableView *view = new QTableView();
    view->setModel(model);
    view->show();

在这里插入图片描述* 视图与模型绑定,模型必须使用new创建,否则视图不能随模型的改变而改变。

//    QStandardItemModel model(4, 2); 错误,没有使用new创建。
    QStandardItemModel *model = new QStandardItemModel(4, 2); //正确,应该使用new创建model。
    model->setHeaderData(0, Qt::Horizontal, QObject::tr("Label"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("Quantity"));
    ui->tableView->setModel(model);
    for(int row = 0; row <4 ; ++row)
    {
        for(int column = 0; column < 2; ++column)
        {
            QModelIndex index = model->index(row, column, QModelIndex());
            model->setData(index, QVariant((row + 1) *(column + 1)));
        }
    }

在这里插入图片描述

项目控件组(Item Widgets)

在这里插入图片描述

树形控件实例

树形控件QTree Widget,其中控件的树节点成为QTreeWidgetItem,这种控件有时很有用处。例如,在飞信软件群发短信时选择联系人的界面中就用到这种有复选框的树形控件。

接下来实现一个简单的树形控件实例。
1、新建项目,保持“创建界面”复选框选择状态。
2、双击“widget.ui”文件,打开Qt的设计器,拖拽一个QTreeWidget控件到widget窗口中。
3、添加以下代码

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    init();
    connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(treeItemChanged(QTreeWidgetItem *, int)));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::init()
{
    ui->treeWidget->clear();
    //第一个分组
    QTreeWidgetItem *group1 = new QTreeWidgetItem(ui->treeWidget);
    group1->setText(0, "group1");
    group1->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable);
    group1->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem11 = new QTreeWidgetItem(group1);
    subItem11->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable);
    subItem11->setText(0, "subItem11");
    subItem11->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem12 = new QTreeWidgetItem(group1);
    subItem12->setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled |Qt::ItemIsSelectable);
    subItem12->setText(0, "subItem12");
    subItem12->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem13 = new QTreeWidgetItem(group1);
    subItem13->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem13->setText(0, "subItem13");
    subItem13->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem14 = new QTreeWidgetItem(group1);
    subItem14->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem14->setText(0, "subItem14");
    subItem14->setCheckState(0, Qt::Unchecked);

    //第二个分组
    QTreeWidgetItem *group2 = new QTreeWidgetItem(ui->treeWidget);
    group2->setText(0, "group2");
    group2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    group2->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem21 = new QTreeWidgetItem(group2);
    subItem21->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem21->setText(0, "subItem21");
    subItem21->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem22 = new QTreeWidgetItem(group2);
    subItem22->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem22->setText(0, "subItem22");
    subItem22->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem23 = new QTreeWidgetItem(group2);
    subItem23->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem23->setText(0, "subItem23");
    subItem23->setCheckState(0, Qt::Unchecked);

    QTreeWidgetItem *subItem24 = new QTreeWidgetItem(group2);
    subItem24->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    subItem24->setText(0, "subItem24");
    subItem24->setCheckState(0, Qt::Unchecked);

}

void Widget::treeItemChanged(QTreeWidgetItem *item, int column)
{
    QString itemText = item->text(0);
    //选中时
    if(Qt::Checked == item->checkState(0))
    {
        QTreeWidgetItem *parent = item->parent();
        int count = item->childCount();
        if(count > 0)
        {
            for(int i = 0; i <count; i++)
            {
                //子字节也选中
                item->child(i)->setCheckState(0, Qt::Checked);
            }
        }
        else {
            //是子节点
            updateParentItem(item);
        }
    }
    else if (Qt::Unchecked == item->checkState(0)) {
        int count = item->childCount();
        if(count > 0)
        {
            for(int i = 0; i <count; i++)
            {
                //子字节也选中
                item->child(i)->setCheckState(0, Qt::Unchecked);
            }
        }
        else {
            //是子节点
            updateParentItem(item);
        }
    }
}

void Widget::updateParentItem(QTreeWidgetItem *item)
{
    QTreeWidgetItem *parent = item->parent();
    if(parent == NULL)
    {
        return ;
    }
    //选中子节点个数
    int selectedCount = 0;
    int childCount = parent->childCount();
    for(int i = 0; i <childCount; i++)
    {
        QTreeWidgetItem *childItem = parent->child(i);
        if(childItem->checkState(0) == Qt::Checked)
        {
            selectedCount++;
        }
    }
    if(selectedCount <= 0)
    {
        //未选中状态
        parent->setCheckState(0, Qt::Unchecked);
    }
    else if (selectedCount > 0 &&selectedCount <childCount) {
        //部分选中
        parent->setCheckState(0, Qt::PartiallyChecked);
    }
    else if (selectedCount == childCount) {
        //选中状态
        parent->setCheckState(0, Qt::Checked);
    }
}

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTreeWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

    void init();
    void updateParentItem(QTreeWidgetItem *item);

public slots:
    void treeItemChanged(QTreeWidgetItem *item, int column);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

跑不了的你 发布了102 篇原创文章 · 获赞 27 · 访问量 4万+ 私信 关注

标签:控件,Widget,QT5,QVariant,Qt,迭代,QString,字符串,类及
来源: https://blog.csdn.net/qq_37596943/article/details/104546651