Qt中文文档

本网站github链接

QtDocumentCN

gitee镜像链接 gitee-QtDocument

微信小程序

微信小程序

wechat

[TOC]

QAbstractAnimation 类

QAbstractAnimation 是所有的动画相关的基类。

QAbstractAnimation 定义了所有动画类相关的基础功能,通过继承该类,您可以实现动画的其它功能,或者添加自定义的特效。

属性方法
头文件#include<QAbstractAnimation>
qmakeQT+=core
自从Qt 4.6
继承QObject
派生QAnimationGroupQPauseAnimationQVariantAnimation

公共成员类型

类型方法
enumDeletionPolicy { KeepWhenStopped, DeleteWhenStopped }
enumDirection { Forward, Backward }
enumState { Stopped, Paused, Running }

属性

属性类型属性类型
currentLoopconst intdurationconst int
currentTimeintloopCountint
directionDirectionstateconst State

公共成员函数

返回类型函数名
QAbstractAnimation(QObject *parent = Q_NULLPTR)
virtual~QAbstractAnimation()
intcurrentLoop() const
intcurrentLoopTime() const
intcurrentTime() const
Directiondirection() const
virtual intduration() const = 0
QAnimationGroup *group() const
intloopCount() const
voidsetDirection(Direction direction)
voidsetLoopCount(int loopCount)
Statestate() const
inttotalDuration() const

公共槽

返回类型函数名
voidpause()
voidresume()
voidsetCurrentTime(int msecs)
voidsetPaused(bool paused)
voidstart(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped)
voidstop()

信号

返回类型函数名
voidcurrentLoopChanged(int currentLoop)
voiddirectionChanged(QAbstractAnimation::Direction newDirection)
voidfinished()
voidstateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)

保护成员函数

返回类型函数名
virtual voidupdateCurrentTime(int currentTime) = 0
virtual voidupdateDirection(QAbstractAnimation::Direction direction)
virtual voidupdateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)

重写保护成员函数

返回类型函数名
virtual boolevent(QEvent *event)

详细介绍

QAbstractAnimation 定义了所有动画共享的功能。通过继承这个类,您可以创建自定义的动画,并将其插入到动画框架中。

动画的进度的当前时间由当前时间(currentLoopTime())控制,数值从0毫秒开始到其最后的持续时间(duration())。该值在动画运行时会自动更新,也可以直接由 setCurrentTime() 来设置。

在任何时候,动画的状态都只有三种:RunningStoppedPaused——由枚举变量 State定义。可以通过函数 start()、stop() 、pause() 或 resume() 来改变当前动画的状态。动画开始时总会重置它的当前时间。若被暂停,则继续播放后会从相同的“当前时间”继续。若动画停止,则无法继续,但会保留“当前时间”(直到再次开始)。QAbstractAnimation 在状态改变时将会发出信号 stateChanged()。

通过设置 loopCount 属性,动画可以循环任意次数。当动画的时间到达 duration() 时,它将重置当前时间并继续运行。循环数为1(默认值)意味着动画只会播放一次。注意,若 duration 为-1,动画将无限播放,直到主动停止;当前时间会无限增长。当当前时间等于 duration() ,并且正在处理最后一次循环时,动画将进入 Stopped 状态,并发送 finished() 信号。

QAbstractAnimation 为子类提供了纯虚函数来跟踪动画的进度:duration() 和 updateCurrentTime()。duration() 函数用于提供动画的持续时间(如上文所述)。当动画时间变化时,动画框架会调用 updateCurrentTime()。通过重新实现该函数,您可以追踪动画进度。注意:此函数的调用间隔和调用次数均未定义,虽然通常每秒会更新60次。

通过重新实现 updateState(),您可以追踪动画状态的改变,这对于不受时间驱动的动画特别有用。

另请参阅:QVariantAnimationQPropertyAnimationQAnimationGroupThe Animation Framework

成员变量文档

enum QAbstractAnimation::DeletionPolicy

函数描述
QAbstractAnimation::KeepWhenStopped0动画停止时不会被删除
QAbstractAnimation::DeleteWhenStopped1动画停止时会被自动删除

enum QAbstractAnimation::Direction

该枚举描述了动画在 Running 状态时的运行的方向。

函数描述
QAbstractAnimation::Forward0“当前时间”随时间递增(即从0向终点/duration 移动)
QAbstractAnimation::Backward1”当前时间“随时间递减(即从终点/duration 向0移动)

enum QAbstractAnimation::State

该枚举描述了动画的状态。

函数描述
QAbstractAnimation::Stopped0动画未运行。这是 QAbstractAnimation 的初始状态,也是 [QAbstractAnimation] 结束后的状态。除非 setCurrentTime() 被调用,或者调用 start() 来启动动画,否则”当前时间“不会改变。
QAbstractAnimation::Paused1动画暂停(即使暂时挂起)。调用 resume() 将恢复动画。
QAbstractAnimation::Running2动画运行中。当控制权处于事件循环中时,QAbstractAnimation 将会有规律地更新”当前时间“,并在适合地时机调用 updateCurrentTime()。

属性文档

currentLoop : const int

此属性存储动画当前的循环数。

此属性描述了动画当前的循环数。默认的循环次数为1,所以当前的循环次数永远为0。若循环总数2的,当动画运行超过其 duration 时将重新开始,并将当前时间重置为0,当前循环数置为1,以此类推。

当当前循环变化时,QAbstractAnimation 会发出 currentLoopChanged() 信号。

存取函数

返回类型函数名
intcurrentLoop() const

通知信号

返回类型函数名
voidcurrentLoopChanged(int currentLoop)

currentTime : int

此属性存储动画当前的时间与进度。

此属性描述了动画当前的时间。您可以通过 setCurrentTime 函数来修改当前时间,也可以调用 start() 让动画运行,当前时间会随动画播放进度自动设置。

动画的当前时间从0开始,在 totalDuration() 结束。

存取函数

返回类型函数名
intcurrentTime() const
voidsetCurrentTime(int msecs)

另请参阅:loopCountcurrentLoopTime()。


direction : Direction

该属性存储动画在 Running 状态时的运行方向。

该方向表明了在 start() 被调用后,时间是从0向动画时长移动,还是从持续时间向0移动。

默认方向为 Forward

存取函数

返回类型函数名
Directiondirection() const
voidsetDirection(Direction direction)

通知信号

返回类型函数名
voiddirectionChanged(QAbstractAnimation::Direction newDirection)

duration : const int

该属性存储动画的持续时间。

如果 duration 为-1,则表示 duration 未定义,此时动画将会忽略 loopCount 属性。

存取函数

属性函数名
virtual intduration() const = 0

loopCount : int

该属性存储动画的循环次数。

此属性用整形描述了动画的循环次数。默认值为1,表示该动画只播放一次,然后停止。通过修改其值,动画会改变循环的次数。当值为0时,动画完全不会运行;当值为-1时,动画将会永远循环直到主动停止。如果动画未设置 duration 属性则无法循环,即只会播放一次。 存取函数

属性函数名
intloopCount() const
voidsetLoopCount(int loopCount)

state : const State

动画状态。 此属性描述了动画的当前状态。当动画状态改变时,QAbstractAnimation 会发射 stateChanged() 信号。

存取函数

属性函数名
Statestate() const

通知信号

属性函数名
voidstateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)

成员函数文档

QAbstractAnimation::QAbstractAnimation(QObject *parent = Q_NULLPTR)

构造 QAbstractAnimation 基类,并将 parent 参数传递给 QObject 的构造函数。

另请参阅:QVariantAnimationQAnimationGroup


[signal] void QAbstractAnimation::currentLoopChanged(int currentLoop)

每当当前循环发生变化时,QAbstractAnimation 会发射该信号。currentLoop 为当前循环。

注意: 属性 currentLoop 的通知信号。

另请参阅:currentLoop() 和 loopCount()。


[signal] void QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection)

每当方向改变时,QAbstractAnimation 会发射该信号。newDirection 为新方向。

注意: 属性 direction 的通知信号。

另请参阅:direction()。


[signal] void QAbstractAnimation::finished()

在动画停止并到达终点之后发送此信号。

该信号在 stateChanged() 之后发射。

另请参阅:stateChanged()。


[slot] void QAbstractAnimation::pause()

暂停动画。当动画暂停时,state() 返回 Paused。在调用 resume() 或 start() 前,currentTime() 的值将会保持不变。若想从当前时间继续,则调用 resume()函数。

另请参阅:start(),state() 和 resume()。


[slot] void QAbstractAnimation::resume()

暂停后恢复动画。当动画恢复时,会发射会发出 resumed() 信号和 stateChanged() 信号。当前时间不会变化。

另请参阅:startpause() 和 state()。


[slot] void QAbstractAnimation::setPaused(bool paused)

pausedtrue,则暂停动画。若 pausefalse,则恢复动画播放。

另请参阅:state(),pause() 和 resume()。


[slot] void QAbstractAnimation::start(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped)

开始动画。policy 参数表示动画在结束后是否会被删除。动画启动时,会发射 stateChanged() 信号,state() 会返回 Running。当控制权回到事件循环时,动画会自动播放,并随播放进度周期性调用 updateCurrentTime(),

若动画当前已被停止或者已经结束,调用 start() 将会充值动画并从头开始。当动画到达终点时,动画将会停止;或者当其循环次数大于1,则会从头开始。

若动画已经在运行中,此函数不会有任何操作。

另请参阅:stop() 和 state()。


[signal] void QAbstractAnimation::stateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)

每当动画的状态从 oldState 变为 newState 时,QAbstractAnimation 会发射此信号。此信号会在虚函数 updateState()被调用后发射。

注意: 属性 state 的通知信号。

另请参阅:updateState()。


[slot] void QAbstractAnimation::stop()

停止动画。当动画停止时,会发射 stateChanged() 信号,state() 返回 Stopped。当前时间不会变化。

若动画到达终点后自动结束(比如 currentLoopTime() == duration() 或者 currentLoop() > loopCount() - 1),则会发射 finished() 信号。

另请参阅:start() 和 state()。


[virtual] QAbstractAnimation::~QAbstractAnimation()

若在运行中则停止动画,然后销毁 QAbstractAnimation。若当前动画是 QAnimationGroup 的一部分,则会在销毁前被自动移除。


int QAbstractAnimation::currentLoopTime() const

返回当前循环中的当前时间。它的范围为0到 duration()。

另请参阅: duration() 和 currentTime()。


[pure virtual] int QAbstractAnimation::duration() const

此纯虚函数返回动画持续时间,并定义 QAbstractAnimation 应该多久更新一次当前时间。持续时间是本地的,并且不包括循环总数。

返回值-1表示动画没有定义持续时间,动画将永远运行下去,直到被主动停止。这对于非时间驱动的动画或者无法预测其持续时间的动画(例如游戏中事件驱动的音频回放)十分有用。

若该动画是并行的 QAbstractAnimation 是并行的,则持续时间是所有动画中最长的。若此动画是顺序的 QAnimationGroup,则持续时间是所有动画的总和。

注意:duration 属性的获取函数。

另请参阅:loopCount()。


[virtual protected] bool QAbstractAnimation::event(QEvent *event)

QObject::event(QEvent *e) 的重新实现。


QAnimationGroup *QAbstractAnimation::group() const

若此动画是 QAnimationGroup 的一部分,则会返回该动画组的指针,否则返回nullptr

另请参阅:QAnimationGroup::addAnimation()。


int QAbstractAnimation::totalDuration() const

返回动画的有效持续时间的综合,包含循环次数。 另请参阅:duration() 和 currentTime()。


[pure virtual protected] void QAbstractAnimation::updateCurrentTime(int currentTime)

此虚函数会当动画的 currentTime 每次发生变化时被调用。

另请参阅:updateState()。


[virtual protected] void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)

此虚函数会在 QAbstractAnimation 的播放方向改变时被调用。参数 direction 表示新的方向。

另请参阅:setDirection(),direction()。


[virtual protected] void QAbstractAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)

此虚函数会在动画的状态改变从 oldState 切换为 newState 时被调用。

另请参阅:start(),stop(),pause() 和 resume()。

[TOC]

QAbstractAudioDeviceInfo类


QAbstractAudioDeviceInfo是音频后端的基类

属性方法
Header:#include<QAbstractAudioDeviceInfo>
qmake:QT += multimedia
Inherits:QObject

简述

公共功能

类型方法
virtual QStringdeviceName() const = 0
virtual boolisFormatSupported(const QAudioFormat &format) const = 0
virtual QAudioFormatpreferredFormat() const = 0
virtual QListQAudioFormat::EndiansupportedByteOrders() = 0
virtual QListsupportedChannelCounts() = 0
virtual QStringListsupportedCodecs() = 0
virtual QListsupportedSampleRates() = 0
virtual QListsupportedSampleSizes() = 0
virtual QListQAudioFormat::SampleTypesupportedSampleTypes() = 0

详细说明


QAbstractAudioDeviceInfo是音频后端的基类。

该类实现了QAudioDeviceInfo的音频功能,即QAudioDeviceInfo类中会保留一个QAbstractAudioDeviceInfo,并对其进行调用。关于QAbstractAudioDeviceInfo的实现的其它功能,您可以参考QAudioDeviceInfo的类与函数文档


成员函数文档


QString QAbstractAudioDeviceInfo::deviceName() const [纯虚函数] 返回音频设备名称


bool QAbstractAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const [纯虚函数] 传入参数QAudioFormat(音频流)类,如果QAbstractAudioDeviceInfo支持的话,返回true(真是不好翻译)


QAudioFormat QAbstractAudioDeviceInfo::preferredFormat() const [纯虚函数] 返回QAbstractAudioDeviceInfo更加倾向于使用的音频流。


QListQAudioFormat::Endian QAbstractAudioDeviceInfo::supportedByteOrders() [纯虚函数] 返回当前支持可用的字节顺序(QAudioFormat :: Endian)列表


QList QAbstractAudioDeviceInfo::supportedChannelCounts() [纯虚函数] 返回当前可用的通道(应该是这样翻译)列表


QStringList QAbstractAudioDeviceInfo::supportedCodecs() [纯虚函数] 返回当前可用编解码器的列表


QList QAbstractAudioDeviceInfo::supportedSampleRates() [纯虚函数] 返回当前可用的采样率列表。(突然发现Google翻译真心吊啊)


QList QAbstractAudioDeviceInfo::supportedSampleSizes() [纯虚函数] 返回当前可用的样本大小列表。


QListQAudioFormat::SampleType QAbstractAudioDeviceInfo::supportedSampleTypes() [纯虚函数] 返回当前可用样本类型的列表。

[TOC]

QAbstractAudioInput类


QAbstractAudioInput类为QAudioInput类提供了访问音频设备的方法。(通过插件的形式)

属性方法
Header:#include <QAbstractAudioInput>
qmake:QT += multimedia
Inherits:QObject

简述

公有的函数

类型方法
virtual intbufferSize() const = 0
virtual intbytesReady() const = 0
virtual qint64elapsedUSecs() const = 0
virtual QAudio::Errorerror() const = 0
virtual QAudioFormatformat() const = 0
virtual intnotifyInterval() const = 0
virtual intperiodSize() const = 0
virtual qint64processedUSecs() const = 0
virtual voidreset() = 0
virtual voidresume() = 0
virtual voidsetBufferSize(int value) = 0
virtual voidsetFormat(const QAudioFormat &fmt) = 0
virtual voidsetNotifyInterval(int ms) = 0
virtual voidsetVolume(qreal) = 0
virtual voidstart(QIODevice *device) = 0
virtual QIODevice*start() = 0
virtual QAudio::Statestate() const = 0
virtual voidstop() = 0
virtual voidsuspend() = 0
virtual qrealvolume() const = 0

信号

类型方法
voiderrorChanged(QAudio::Error error)
voidnotify()
voidstateChanged(QAudio::State state)

详细描述

QAbstractAudioInput类为QAudioInput类提供了访问音频设备的方法。(通过插件的形式) QAudioDeviceInput类中保留了一个QAbstractAudioInput的实例,并且调用的函数与QAbstractAudioInput的一致。

译者注:也就是说QAudioDeviceInput调用的函数实际上是QAbstractAudioInput的函数,就封装了一层相同函数名吧。可以自己看看源码。)

这意味着QAbstractAudioInput是实现音频功能的。有关功能的描述,可以参考QAudioInput类。 另见QAudioInput函数


成员函数文档


int QAbstractAudioInput::bufferSize() const [纯虚函数]

以毫秒为单位返回音频缓冲区的大小


int QAbstractAudioInput::bytesReady() const [纯虚函数]

以字节(bytes)为单位返回可读取的音频数据量


qint64 QAbstractAudioInput**::elapsedUSecs() const [纯虚函数]

返回调用start()函数以来的毫秒数,包括空闲时间与挂起状态的时间


QAudio::Error QAbstractAudioInput::error() const [纯虚函数]

返回错误的状态


void QAbstractAudioInput::errorChanged(QAudio::Error error) [信号signal]

当错误状态改变时,该信号被发射


QAudioFormat QAbstractAudioInput::format() const [纯虚函数]

返回正在使用的QAudioFormat(这个类是储存音频流相关的参数信息的) 另参见setFormat()函数


void QAbstractAudioInput::notify() [信号signal]

当音频数据的x ms通过函数setNotifyInterval()调用之后,这个信号会被发射。


int QAbstractAudioInput::notifyInterval() const [纯虚函数]

以毫秒为单位返回通知间隔


int QAbstractAudioInput::periodSize() const [纯虚函数]

以字节为单位返回其周期


qint64 QAbstractAudioInput::processedUSecs() const [纯虚函数]

返回自start()函数被调用之后处理的音频数据量(以毫秒为单位)


void QAbstractAudioInput::reset() [纯虚函数]

将所有音频数据放入缓冲区,并将缓冲区重置为零


void QAbstractAudioInput::resume() [纯虚函数]

在音频数据暂停后继续处理


void QAbstractAudioInput::setBufferSize(int value) [纯虚函数]

将音频缓冲区大小设置为value大小(以毫秒为单位) 另参阅bufferSize()函数


void QAbstractAudioInput::setFormat(const QAudioFormat &fmt) [纯虚函数]

设置音频格式,设置格式的时候只能在QAudio的状态为StoppedState时(QAudio::StoppedState)


void QAbstractAudioInput::setNotifyInterval(int ms) [纯虚函数]

设置发送notify()信号的时间间隔。这个ms时间间隔与操作系统平台相关,并不是实际的ms数。


void QAbstractAudioInput::setVolume(qreal) [纯虚函数]

另见volume()函数 (设置这里应该是设置音量的值,Volume在英文中有音量的意思,官方文档这里根本就没有任何说明,说去参考valume()函数,可是valume()说又去参考SetValume()函数,这是互相甩锅的节奏么???坑爹啊!!!)


void QAbstractAudioInput::start(QIODevice *device) [纯虚函数]

使用输入参数QIODevice *device来传输数据


QIODevice *QAbstractAudioInput::start() [纯虚函数]

返回一个指向正在用于正在处理数据QIODevice的指针。这个指针可以用来直接读取音频数据。


QAudio::State QAbstractAudioInput::state() const [纯虚函数]

返回处理音频的状态


void QAbstractAudioInput::stateChanged(QAudio::State state) [信号signal]

当设备状态改变时,会发出这个信号


void QAbstractAudioInput::stop() [纯虚函数]

停止音频输入(因为这是个QAbstractAudioInput类啊,输入类啊,暂时这么解释比较合理。)


void QAbstractAudioInput::suspend() [纯虚函数]

停止处理音频数据,保存缓冲的音频数据


qreal QAbstractAudioInput::volume() const [纯虚函数]

另见setVolume()(内心os:参考我解释setVolume()函数的说明,这里应该是返回其音量)


[TOC] #QAbstractAudioOutput类


QAbstractAudioOutput类是音频后端的基类

属性方法
头文件包含: #include <QAbstractAudioOutput>
qmake写法:QT += multimedia
继承:QObject

简述

public函数

类型函数名
virtual intbufferSize() const = 0
virtual intbytesFree() const = 0
virtual QStringcategory() const
virtual qint64elapsedUSecs() const = 0
virtual QAudio::Errorerror() const = 0
virtual QAudioFormatformat() const = 0
virtual intnotifyInterval() const = 0
virtual intperiodSize() const = 0
virtual qint64processedUSecs() const = 0
virtual voidreset() = 0
virtual voidresume() = 0
virtual voidsetBufferSize(int value) = 0
virtual voidsetCategory(const QString &)
virtual voidsetFormat(const QAudioFormat &fmt) = 0
virtual voidsetNotifyInterval(int ms) = 0
virtual voidsetVolume(qreal volume)
virtual voidstart(QIODevice *device) = 0
virtual QIODevice *start() = 0
virtual QAudio::Statestate() const = 0
virtual voidstop() = 0
virtual voidsuspend() = 0
virtual qrealvolume() const

信号

类型函数名
voiderrorChanged(QAudio::Error error)
voidnotify()
voidstateChanged(QAudio::State state)

详细描述

QAbstractAudioOutput类是音频后端的基类。 QAbstractAudioOutput类是QAudioOutput类的实现类。QAudioOutput的实现实际上是调用的QAbstractAudioOutput类,有关实现相关的功能,请参考QAudioOutput()类中的函数说明。


成员函数


int QAbstractAudioOutput::bufferSize() const [纯虚函数] 以字节为单位,返回音频缓冲区的大小。

另见setBufferSize()函数


int QAbstractAudioOutput :: bytesFree ()const [纯虚函数] 返回音频缓冲区的可用空间(以字节为单位)


QString QAbstractAudioOutput::category() const [虚函数 virtual] 音频缓冲区的类别(官方文档没有,这是我个人经验,当然可能有误,望指正) 另见setCategory()


qint64 QAbstractAudioOutput::elapsedUSecs() const [纯虚函数 pure virtual] 返回调用start()函数之后的毫秒数,包括处于空闲状态的时间和挂起状态的时间。


QAudio::Error QAbstractAudioOutput::error() const [纯虚函数 pure virtual] 返回错误状态。


void QAbstractAudioOutput::errorChanged(QAudio::Error error) [信号 signal] 当错误状态改变时,该信号被发射。


QAudioFormat QAbstractAudioOutput :: format ()const [纯虚函数 pure virtual] 返回正在使用的QAudioFormat()类 另见setFormat()


void QAbstractAudioOutput::notify() [信号 signal] 当函数setNotifyInterval(x)函数已经调用,即音频数据的时间间隔已经被设置时。该信号被发射。(就是调用setNotifyInterval(x)后,这个信号会被发射。官方文档讲的好详细啊=。=)


int QAbstractAudioOutput::notifyInterval() const [纯虚函数 pure virtual] 以毫秒为单位,返回时间间隔 另见函数setNotifyInterval()


int QAbstractAudioOutput::periodSize() const [纯虚函数 pure virtual] 以字节为单位返回周期大小。


qint64 QAbstractAudioOutput::processedUSecs() const [纯虚函数 pure virtual] 返回自调用start()函数后处理的音频数据量(单位为毫秒)


void QAbstractAudioOutput::reset() [纯虚函数 pure virtual] 将所有音频数据放入缓冲区,并将缓冲区重置为零。


void QAbstractAudioOutput::resume() [纯虚函数 pure virtual] 继续处理暂停后的音频数据 (也就是暂停后继续的意思呗)


void QAbstractAudioOutput::setBufferSize(int value) [纯虚函数 pure virtual] 重新设置音频缓冲区的大小(以字节为单位 即输入参数value) 另见bufferSize()函数


void QAbstractAudioOutput::setCategory(const QString &) [虚函数 virtual] 参见函数category()


void QAbstractAudioOutput::setFormat(const QAudioFormat &fmt) [纯虚函数 pure virtual] QAbstractAudioOutput设置QAudioFormat类,只有当QAudio状态为QAudio::StoppedState时,音频格式才会被设置成功。 另见函数format()


void QAbstractAudioOutput::setNotifyInterval(int ms) [纯虚函数 pure virtual] 设置发送notify()信号的时间间隔。这个ms并不是实时处理的音频数据中的ms数。这个时间间隔是平台相关的。 另见notifyInterval()


void QAbstractAudioOutput::setVolume(qreal volume) [虚函数 virtual] 设置音量。音量的范围为[0.0 - 1.0]。 另见函数volume()


void QAbstractAudioOutput::start(QIODevice device) [纯虚函数 pure virtual] 调用start()函数时,输入参数QIODevice类型的变量device,用于音频后端处理数据传输。


*QIODevice QAbstractAudioOutput::start() [纯虚函数 pure virtual] 返回一个指向正在处理数据传输的QIODevice类型的指针,这个指针是可以被写入的,用于处理音频数据。(参考上边的函数是咋写入的)


QAudio::State QAbstractAudioOutput::state() const [纯虚函数 pure virtual] 返回音频处理的状态。


void QAbstractAudioOutput::stateChanged(QAudio::State state) [信号 signal] 当音频状态变化的时候,该信号被发射


void QAbstractAudioOutput::stop() [纯虚函数 pure virtual] 停止音频输出


void QAbstractAudioOutput::suspend() [纯虚函数 pure virtual] 停止处理音频数据,保存处理的音频数据。(就是暂停的意思啊=。=)


qreal QAbstractAudioOutput::volume() const [虚函数 virtual] 返回音量。音量范围为[0.0 - 1.0] 另参阅函数setVolume()


[TOC]

QAbstractAxis


QAbstractAxis类是用于专门处理坐标轴的类

属性方法
头文件: #include <QAbstractAxis>
实例化:AbstractAxis
继承:QObject
派生:QBarCategoryAxis, QDateTimeAxis, QLogValueAxis, and QValueAxis

简述


公共类型

类型方法
enumAxisType { AxisTypeNoAxis, AxisTypeValue, AxisTypeBarCategory, AxisTypeCategory, AxisTypeDateTime, AxisTypeLogValue }
flagsAxisTypes

属性

函数名类型
alignment :const Qt::Alignment
color :QColor
gridLineColor :QColor
gridLinePen :QPen
gridVisible :bool
labelsAngle :int
labelsBrush :QBrush
labelsColor :QColor
labelsFont :QFont
labelsVisible :bool
linePen :QPen
lineVisible :bool
minorGridLineColor :QColor
minorGridLinePen :QPen
minorGridVisible :bool
orientation :const Qt::Orientation
reverse :bool
shadesBorderColor :QColor
shadesBrush :QBrush
shadesColor :QColor
shadesPen :QPen
shadesVisible :bool
titleBrush :QBrush
titleFont :QFont
titleText :QString
titleVisible :bool
visible :bool

Public Functions

类型函数名
~QAbstractAxis()
Qt::Alignmentalignment() const
QColorgridLineColor()
QPengridLinePen() const
voidhide()
boolisGridLineVisible() const
boolisLineVisible() const
boolisMinorGridLineVisible() const
boolisReverse() const
boolisTitleVisible() const
boolisVisible() const
intlabelsAngle() const
QBrushlabelsBrush() const
QColorlabelsColor() const
QFontlabelsFont() const
boollabelsVisible() const
QPenlinePen() const
QColorlinePenColor() const
QColorminorGridLineColor()
QPenminorGridLinePen() const
Qt::Orientationorientation() const
voidsetGridLineColor(const QColor &color)
voidsetGridLinePen(const QPen &pen)
voidsetGridLineVisible(bool visible = true)
voidsetLabelsAngle(int angle)
voidsetLabelsBrush(const QBrush &brush)
voidsetLabelsColor(QColor color)
voidsetLabelsFont(const QFont &font)
voidsetLabelsVisible(bool visible = true)
voidsetLinePen(const QPen &pen)
voidsetLinePenColor(QColor color)
voidsetLineVisible(bool visible = true)
voidsetMax(const QVariant &max)
voidsetMin(const QVariant &min)
voidsetMinorGridLineColor(const QColor &color)
voidsetMinorGridLinePen(const QPen &pen)
voidsetMinorGridLineVisible(bool visible = true)
voidsetRange(const QVariant &min, const QVariant &max)
voidsetReverse(bool reverse = true)
voidsetShadesBorderColor(QColor color)
voidsetShadesBrush(const QBrush &brush)
voidsetShadesColor(QColor color)
voidsetShadesPen(const QPen &pen)
voidsetShadesVisible(bool visible = true)
voidsetTitleBrush(const QBrush &brush)
voidsetTitleFont(const QFont &font)
voidsetTitleText(const QString &title)
voidsetTitleVisible(bool visible = true)
voidsetVisible(bool visible = true)
QColorshadesBorderColor() const
QBrushshadesBrush() const
QColorshadesColor() const
QPenshadesPen() const
boolshadesVisible() const
voidshow()
QBrushtitleBrush() const
QFonttitleFont() const
QStringtitleText() const
virtual AxisTypetype() const = 0

信号

类型函数名
voidcolorChanged(QColor color)
voidgridLineColorChanged(const QColor &color)
voidgridLinePenChanged(const QPen &pen)
voidgridVisibleChanged(bool visible)
voidlabelsAngleChanged(int angle)
voidlabelsBrushChanged(const QBrush &brush)
voidlabelsColorChanged(QColor color)
voidlabelsFontChanged(const QFont &font)
voidlabelsVisibleChanged(bool visible)
voidlinePenChanged(const QPen &pen)
voidlineVisibleChanged(bool visible)
voidminorGridLineColorChanged(const QColor &color)
voidminorGridLinePenChanged(const QPen &pen)
voidminorGridVisibleChanged(bool visible)
voidreverseChanged(bool reverse)
voidshadesBorderColorChanged(QColor color)
voidshadesBrushChanged(const QBrush &brush)
voidshadesColorChanged(QColor color)
voidshadesPenChanged(const QPen &pen)
voidshadesVisibleChanged(bool visible)
voidtitleBrushChanged(const QBrush &brush)
voidtitleFontChanged(const QFont &font)
voidtitleTextChanged(const QString &text)
voidtitleVisibleChanged(bool visible)
voidvisibleChanged(bool visible)

详细说明


QAbstractAxis是专门用于处理坐标轴的基类。

每一个连续的序列可以绑定到一个或者多个水平轴和垂直轴,但是不同域的混合轴的类型是不支持的。比如在同一个方向指定QValueAxis和QLogValueAxis。

每个轴的元素(比如轴线,标题,标签,网格线,阴影,可见性)都是可以控制的。


成员变量

enum QAbstractAxis::AxisType flags QAbstractAxis::AxisTypes


这个枚举类型指定了轴对象的类型

变量
QAbstractAxis::AxisTypeNoAxis0x0
QAbstractAxis::AxisTypeValue0x1
QAbstractAxis::AxisTypeBarCategory0x2
QAbstractAxis::AxisTypeCategory0x4
QAbstractAxis::AxisTypeDateTime0x8
QAbstractAxis::AxisTypeLogValue0x10

AxisTypesQFlags<AxisType>的typedef。它是AxisType类型的组合。 (也就是个宏呗)


alignment : const Qt::Alignment 该属性是轴的对齐属性 其值可以为 Qt::AlignLeft, Qt::AlignRight, Qt::AlignBottom, or Qt::AlignTop. 相关函数

类型函数名
Qt::Alignmentalignment() const

color : QColor 该属性是指坐标轴与刻度的颜色

相关函数

类型函数名
QColorlinePenColor() const
voidsetLinePenColor(QColor color)

通知信号

类型函数名
voidcolorChanged(QColor color)

gridLineColor : QColor 该属性是指网格线的颜色

相关函数

类型函数名
QColorgridLineColor()
voidsetGridLineColor(const QColor &color)

通知信号

类型函数名
voidgridLineColorChanged(const QColor &color)

gridLinePen : QPen 该属性是指绘制网格线的笔

相关函数

类型函数名
QPengridLinePen() const
voidsetGridLinePen(const QPen &pen)

通知信号

类型函数名
voidgridLinePenChanged(const QPen &pen)

gridVisible : bool 该属性是网格线是否可见

相关函数

类型函数名
QPengridLinePen() const
voidsetGridLinePen(const QPen &pen)

通知信号

类型函数名
voidgridLinePenChanged(const QPen &pen)

labelsAngle : int 该属性以度数保存轴坐标的角度

相关函数

类型函数名
intlabelsAngle() const
voidsetLabelsAngle(int angle)

通知信号

类型函数名
voidlabelsAngleChanged(int angle)

labelsBrush : QBrush 该属性表示用于绘制标签的画笔 只有画刷的颜色是相关的(这句话其实我不太理解Only the color of the brush is relevant.)

相关函数

类型函数名
QBrushlabelsBrush() const
voidsetLabelsBrush(const QBrush &brush)

通知信号

类型函数名
voidlabelsBrushChanged(const QBrush &brush)

labelsColor : QColor 该属性表示轴标签的颜色

相关函数

类型函数名
QColorlabelsColor() const
voidsetLabelsColor(QColor color)

通知信号

类型函数名
voidlabelsColorChanged(QColor color)

labelsFont : QFont 该属性表示轴标签的字体信息

相关函数

类型函数名
QFontlabelsFont() const
voidsetLabelsFont(const QFont &font)

通知信号

类型函数名
voidlabelsFontChanged(const QFont &font)

labelsVisible : bool 该属性表示轴标签是否可见

相关函数

类型函数名
boollabelsVisible() const
voidsetLabelsVisible(bool visible = true)

通知信号

类型函数名
voidlabelsVisibleChanged(bool visible)

linePen : QPen 该属性表示绘制轴线的笔相关

相关函数

类型函数名
QPenlinePen() const
voidsetLinePen(const QPen &pen)

通知信号

类型函数名
voidlinePenChanged(const QPen &pen)

lineVisible : bool 该属性表示轴线是否可见

相关函数

类型函数名
boolisLineVisible() const
voidsetLineVisible(bool visible = true)

通知信号

类型函数名
voidlineVisibleChanged(bool visible)

minorGridLineColor : QColor 该属性表示副格线的颜色 仅适用于支持副网格线的轴

相关函数

类型函数名
QColorminorGridLineColor()
voidsetMinorGridLineColor(const QColor &color)

通知信号

类型函数名
voidminorGridLineColorChanged(const QColor &color)

minorGridLinePen : QPen 该属性表示副格线的笔 仅适用于支持副网格线的轴

相关函数

类型函数名
QPenminorGridLinePen() const
voidsetMinorGridLinePen(const QPen &pen)

通知信号

类型函数名
voidminorGridLinePenChanged(const QPen &pen)

minorGridVisible : bool 该属性表示副格线是否可见 仅适用于支持副网格线的轴

相关函数

类型函数名
boolisMinorGridLineVisible() const
voidsetMinorGridLineVisible(bool visible = true)

通知信号

类型函数名
voidminorGridVisibleChanged(bool visible)

orientation : const Qt::Orientation 该属性表示坐标轴的方向。 当坐标轴被添加到图表时,该属性为Qt::Horizontal或者Qt::Vertical

相关函数

类型函数名
Qt::Orientationorientation() const

reverse : bool 该属性表示是否使用反转轴。 该值默认为false。 反转轴由直线,样条,散列图系列以及笛卡尔图表组成的区域支持。如果一个方向相反,或者行为为定义,则所有相同方向的所有轴必须保持一致。

相关函数

类型函数名
boolisReverse() const
voidsetReverse(bool reverse = true)

通知信号

类型函数名
voidreverseChanged(bool reverse)

shadesBorderColor : QColor 该属性表示坐标轴阴影的边框(笔)颜色

相关函数

类型函数名
QColorshadesBorderColor() const
voidsetShadesBorderColor(QColor color)

通知信号

类型函数名
voidshadesBorderColorChanged(QColor color)

shadesBrush : QBrush 该属性表示用于绘制轴阴影的画笔(网格线之间的区域)

相关函数

类型函数名
QPenshadesPen() const
voidsetShadesPen(const QPen &pen)

通知信号

类型函数名
voidshadesPenChanged(const QPen &pen)

shadesVisible : bool 该属性表示轴阴影是否可见

相关函数

类型函数名
boolshadesVisible() const
voidsetShadesVisible(bool visible = true)

通知信号

类型函数名
voidshadesVisibleChanged(bool visible)

titleBrush : QBrush 该属性表示用于绘制坐标轴标题文本的画笔。 只影响画刷的颜色。

相关函数

类型函数名
QBrushtitleBrush() const
voidsetTitleBrush(const QBrush &brush)

通知信号

类型函数名
voidtitleBrushChanged(const QBrush &brush)

titleFont : QFont 该属性表示坐标轴标题的字体。

相关函数

类型函数名
QFonttitleFont() const
voidsetTitleFont(const QFont &font)

通知信号

类型函数名
voidtitleFontChanged(const QFont &font)

titleText : QString 该属性表示坐标轴的标题 默认为空,坐标轴的标题支持HTML的格式。

相关函数

类型函数名
QStringtitleText() const
voidsetTitleText(const QString &title)

通知信号

类型函数名
voidtitleTextChanged(const QString &text)

titleVisible : bool 该属性表示坐标轴的可见性。 默认值为true。

相关函数

类型函数名
boolisTitleVisible() const
voidsetTitleVisible(bool visible = true)

通知信号

类型函数名
voidtitleVisibleChanged(bool visible)

visible : bool 该属性表示坐标轴的可见性。

相关函数

类型函数名
boolisVisible() const
voidsetVisible(bool visible = true)

通知信号

类型函数名
voidvisibleChanged(bool visible)

##成员函数


QAbstractAxis::~QAbstractAxis() 析构函数,销毁轴对象,当一个坐标轴添加到图表时,该图表获得该坐标轴的所有权。


void QAbstractAxis::colorChanged(QColor color) [信号] 当坐标轴的颜色变化时,该信号被发射。 注意:属性color的通知信号。


void QAbstractAxis::gridLineColorChanged(const QColor &color) [信号] 当绘制网格线的笔的颜色改变时,该信号被发射。 注意:属性gridLineColor的通知信号。


QPen QAbstractAxis::gridLinePen() const 返回用于绘制网格的笔。 注意:属性gridLinePen的Getter函数。 另参见函数setGridLinePen()。


void QAbstractAxis :: gridLinePenChanged(const QPen&pen) [信号] 当用于绘制网格线的笔变化时,会发出此信号。 注意:属性gridLinePen的通知信号。


void QAbstractAxis::gridVisibleChanged(bool visible) [信号] 当坐标轴的网格线的可见性变化时,发出该信号。 注意:属性gridVisible的通知信号。


void QAbstractAxis::hide() 使坐标轴,阴影,标签,网格线不可见。


void QAbstractAxis::labelsAngleChanged(int angle) [信号] 当坐标轴标签的角度变化时,发出该信号。 注意:属性标签角度的通知信号


QBrush QAbstractAxis::labelsBrush() const 返回用于绘制标签的画笔。 注意:属性labelsBrush的Getter函数。 另参见setLabelsBrush().


void QAbstractAxis::labelsBrushChanged(const QBrush &brush) [信号] 当用于绘制坐标轴标签的画笔改变时,会发出此信号。 属性Brush的通知信号。


void QAbstractAxis :: labelsColorChanged(QColor color) [信号signal] 当坐标轴标签的颜色改变时,会发出此信号。 属性labelsColor的通知信号。


**QFont QAbstractAxis::labelsFont()const ** 返回用于绘制标签的字体。 注意:属性labelsFont的Getter函数。 另参见函数setLabelsFont()。


void QAbstractAxis :: labelsFontChanged(const QFont&font)[信号] 当坐标轴的字体改变时,会发出此信号。 属性labelsFont的通知信号。


void QAbstractAxis::labelsVisibleChanged(bool visible) [信号] 当坐标轴标签的可见性变化时,会发出此信号。 属性labelsVisible的通知信号。


QPen QAbstractAxis::linePen() const 返回用于绘制轴线与刻度线的笔。 注意:属性linePen的Getter函数。 另参阅函数setLinePen()。


void QAbstractAxis::linePenChanged(const QPen &pen) [信号] 当绘制坐标轴的笔变化时,会发出此信号。 注意:属性linePen的通知信号。


void QAbstractAxis::lineVisibleChanged(bool visible) [信号] 当坐标轴线的可见性变化时,会发出此信号。 注意:属性lineVisible的通知信号。


void QAbstractAxis::minorGridLineColorChanged(const QColor &color) [信号] 当绘制副格线的笔的颜色变化时,该信号被发射。 注意:属性minorGridLineColor的通知信号。


void QAbstractAxis::minorGridLinePenChanged(const QPen &pen) [信号] 当绘制副格线的笔变化时,该信号被发射。 注意:属性minorGridLinePen的通知信号。


void QAbstractAxis::minorGridVisibleChanged(bool visible) [信号] 当绘制副格线的可见性变化时,该信号被发射。 注意:属性minorGridVisible的通知信号。


Qt::Orientation QAbstractAxis::orientation() const 返回坐标轴的方向(垂直或者水平) 注意:坐标轴方向的Getter函数。


void QAbstractAxis::setGridLinePen(const QPen &pen) 设置绘制网格线的笔。 注意:gridLinePen的Setter函数。 另参见函数gridLinePen()。


void QAbstractAxis::setLabelsBrush(const QBrush &brush) 设置用于绘制标签的画笔。 注意:属性LabelsBrush的Setter函数。 另参阅labelsBrush().


void QAbstractAxis::setLabelsFont(const QFont &font) 设置用于绘制标签的字体相关 注意:属性labelsFont的Setter函数。 另参阅函数labelsFont()。


void QAbstractAxis::setLinePen(const QPen &pen) 设置用于绘制坐标轴线和刻度线的笔。 注意:属性linePen的Setter函数。 另参见函数linePen()。


void QAbstractAxis::setLineVisible(bool visible = true) 设置坐标轴线与刻度线是否可见。 注意:属性lineVisible的Setter函数 另参见函数isLineVisible()。


void QAbstractAxis::setMax(const QVariant &max) 设置坐标轴上显示的最大值。根据当前坐标轴的类型,最大值参数会被转换为适当的值。如果转化失败,该函数设置无效。


void QAbstractAxis::setMin(const QVariant &min) 设置坐标轴上显示的最小值。根据当前坐标轴的类型,最小值参数会被转换为适当的值。如果转化失败,该函数设置无效。


void QAbstractAxis::setRange(const QVariant &min, const QVariant &max) 设置坐标轴的范围。根据当前坐标轴的类型,最大值最小值会被转换为适当的值。如果转化失败,该函数设置无效。


void QAbstractAxis::setShadesBrush(const QBrush &brush) 设置用于绘制阴影的画笔。 注意:属性shadesBrush的Setter函数。 另参见函数shadesBrush().


void QAbstractAxis::setShadesPen(const QPen &pen) 设置用于绘制阴影的笔。 注意:属性shadesPen的Setter函数。 另参见函数shadesPen().


void QAbstractAxis::setTitleBrush(const QBrush &brush) 设置用于绘制标题的画笔。 注意:属性titleBrush的Setter函数。 另参见函数titleBrush().


void QAbstractAxis::setTitleFont(const QFont &font) 设置用于绘制标题的笔。 注意:属性titleFont的Setter函数。 另参见函数titleFont().


void QAbstractAxis::setVisible(bool visible = true) 设置坐标轴,阴影,标签,网格线是否可见。 注意:属性visible的Setter函数。 另参见函数isVisible().


void QAbstractAxis::shadesBorderColorChanged(QColor color) [信号signal] 当绘制坐标轴边框的颜色变化时,会发出此信号。 注意:属性shadesBorderColor的通知信号。


QBrush QAbstractAxis::shadesBrush() const 返回用于绘制阴影的画笔。 注意:属性shadesBrush()的Getter函数。 另参阅函数setShadesBrush().


void QAbstractAxis::shadesBrushChanged(const QBrush &brush) [信号signal] 当绘制坐标轴阴影的画刷变化时,会发出此信号。 注意:属性shadesBrush()的通知信号。


void QAbstractAxis::shadesColorChanged(QColor color) [信号signal] 当绘制坐标轴阴影颜色发生变化时,会发出此信号。 注意:属性shadesColor()的通知信号。


QPen QAbstractAxis::shadesPen() const 返回用于绘制阴影的笔。 注意:属性shadesPen()的Getter函数 另参阅函数setShadesPen().


void QAbstractAxis::shadesPenChanged(const QPen &pen) [信号signal] 当绘制坐标轴阴影的笔发生变化时,会发出此信号。 注意:属性shadesPen()的通知信号。


void QAbstractAxis::shadesVisibleChanged(bool visible) [信号signal] 当坐标轴的阴影可见性变化时,会发出此信号。 注意:属性shadesVisible()的通知信号。


void QAbstractAxis::show() 使坐标轴,阴影,标签,网格线可见。


QBrush QAbstractAxis::titleBrush() const 返回用于绘制标题的画刷 注意:属性titleBrush的Getter函数 另参阅函数setTitleBrush()


void QAbstractAxis::titleBrushChanged(const QBrush &brush) [信号signal] 当绘制坐标轴标题的画刷变化时,该信号被发射 注意:titleBrush的通知信号。


QFont QAbstractAxis::titleFont() const 返回绘制标题的笔相关属性。 注意:titleFont的Getter函数 另参阅函数setTitleFont()


void QAbstractAxis::titleFontChanged(const QFont &font) [信号 signal] 当坐标轴标题的字体属性更改时,会发出此信号。 注意:titleFont的通知信号。


void QAbstractAxis::titleTextChanged(const QString &text) [信号 signal] 当坐标轴标题的文本内容改变时,会发出此信号。 注意:titleText的通知信号。


void QAbstractAxis::titleVisibleChanged(bool visible) [信号 signal] 当坐标轴的标题文本的可见性变化时,会发出此信号。 注意:titleVisible的通知信号


AxisType QAbstractAxis::type() const 返回坐标轴的类型


void QAbstractAxis::visibleChanged(bool visible) 当坐标轴的可见性变化时,会发出此信号。 注意:坐标轴的visible的通知信号

[TOC]

QAbstractBarSeries


QAbstractBarSeries是所有柱状图/条形图系列的基类

属性方法
头文件:#include<QAbstractBarSeries>
实例化:AbstractBarSeries
继承:QAbstractSeries
派生:QBarSeries, QHorizontalBarSeries, QHorizontalPercentBarSeries, QHorizontalStackedBarSeries, QPercentBarSeries, and QStackedBarSeries

简述


公共类型

类型方法
enumLabelsPosition { LabelsCenter, LabelsInsideEnd, LabelsInsideBase, LabelsOutsideEnd }

属性

函数名类型
barWidth :qreal
count :const int
labelsAngle :qreal
5个属性继承自QAbstractSeries
1个属性继承自QObject

Public Functions

类型函数名
virtual~QAbstractBarSeries()
boolappend(QBarSet *set)
boolappend(QList<QBarSet *> sets)
QList<QBarSet *>barSets() const
qrealbarWidth() const
voidclear()
intcount() const
boolinsert(int index, QBarSet *set)
boolisLabelsVisible() const
qreallabelsAngle() const
QStringlabelsFormat() const
QAbstractBarSeries::LabelsPositionlabelsPosition() const
boolremove(QBarSet *set)
voidsetBarWidth(qreal width)
voidsetLabelsAngle(qreal angle)
voidsetLabelsFormat(const QString &format)
voidsetLabelsPosition(QAbstractBarSeries::LabelsPosition position)
voidsetLabelsVisible(bool visible = true)
booltake(QBarSet *set)
15个公共函数继承自QAbstractSeries
32个公共函数继承自QObject

信号

类型函数名
voidbarsetsAdded(QList<QBarSet *> sets)
voidbarsetsRemoved(QList<QBarSet *> sets)
voidclicked(int index, QBarSet *barset)
voidcountChanged()
voiddoubleClicked(int index, QBarSet *barset)
voidhovered(bool status, int index, QBarSet *barset)
voidlabelsAngleChanged(qreal angle)
voidlabelsFormatChanged(const QString &format)
voidlabelsPositionChanged(QAbstractBarSeries::LabelsPosition position)
voidlabelsVisibleChanged()
voidpressed(int index, QBarSet *barset)
voidreleased(int index, QBarSet *barset)

额外继承的

1个公共槽继承自QObject 11个静态成员函数继承自QObject 9个保护函数继承自QObject


详细说明

QAbstractBarSeries类是所有条形柱的抽象类。

在条形图中,条形柱被定义为包含一种数据的集合。条形柱的位置由其类别与数值来决定。条形柱组合则是属于同一类别的条形柱。条形柱的显示则是由创建图表的时候决定的。

如果使用QValueAxis来代替QBarCategoryAxis当做图表的主轴。那么条形柱别按照索引值来分类。

可以参考Qt Example(example 这里我还没有来得及翻译)


成员类型

enum QAbstractBarSeries::LabelsPosition**

这个枚举值表示的是条形柱标签的位置:

枚举值数值描述
QAbstractBarSeries::LabelsCenter0中部
QAbstractBarSeries::LabelsInsideEnd1顶部
QAbstractBarSeries::LabelsInsideBase2底部
QAbstractBarSeries::LabelsOutsideEnd3外部

QAbstractItemModel 类

QAbstractItemModel类为项模型类提供了抽象接口。更多...

属性方法
头文件#include <QAbstractItemModel>
qmakeQT += core
继承QObject
派生QAbstractListModelQAbstractProxyModelQAbstractTableModelQConcatenateTablesProxyModelQDirModelQFileSystemModelQStandardItemModel

公共成员类型

类型类型名称
enum classCheckIndexOption { NoOption, IndexIsValid, DoNotUseParent, ParentIsInvalid }
flagsCheckIndexOptions
enumLayoutChangeHint { NoLayoutChangeHint, VerticalSortHint, HorizontalSortHint }

公共成员函数

类型函数名称
QAbstractItemModel(QObject *parent = nullptr)
virtual~QAbstractItemModel()
virtual QModelIndexbuddy(const QModelIndex &index) const
virtual boolcanDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const s
virtual boolcanFetchMore(const QModelIndex &parent) const
boolcheckIndex(const QModelIndex &index, QAbstractItemModel::CheckIndexOptions options = CheckIndexOption::NoOption) const
virtual intcolumnCount(const QModelIndex &parent = QModelIndex()) const = 0
virtual QVariantdata(const QModelIndex &index, int role = Qt::DisplayRole) const = 0
virtual booldropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
virtual voidfetchMore(const QModelIndex &parent)
virtual Qt::ItemFlagsflags(const QModelIndex &index) const
virtual boolhasChildren QModelIndex &parent = QModelIndex()) const
boolhasIndex row, int column, const QModelIndex &parent = QModelIndex()) const
virtual QVariantheaderData section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
virtual QModelIndexindex row, int column, const QModelIndex &parent = QModelIndex()) const = 0
boolinsertColumn column, const QModelIndex &parent = QModelIndex())
virtual boolinsertColumns column, int count, const QModelIndex &parent = QModelIndex())
boolinsertRow(int row, const QModelIndex &parent = QModelIndex())
virtual boolinsertRows row, int count, const QModelIndex &parent = QModelIndex())
virtual QMap<int, QVariant>itemData QModelIndex &index) const
virtual QModelIndexListmatch QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags (Qt::MatchStartsWith
virtual QMimeData *mimeData QModelIndexList &indexes) const
virtual QStringListmimeTypes const
boolmoveColumn QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild)
virtual boolmoveColumns QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild)
boolmoveRow QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild)
virtual boolmoveRows QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
virtual QModelIndexparent QModelIndex &index) const = 0
boolremoveColumn column, const QModelIndex &parent = QModelIndex())
virtual boolremoveColumns column, int count, const QModelIndex &parent = QModelIndex())
boolremoveRow row, const QModelIndex &parent = QModelIndex())
virtual boolremoveRows row, int count, const QModelIndex &parent = QModelIndex())
virtual QHash<int, QByteArray>roleNames const
virtual introwCount QModelIndex &parent = QModelIndex()) const = 0
virtual boolsetData QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
virtual boolsetHeaderData section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)
virtual boolsetItemData QModelIndex &index, const QMap<int, QVariant> &roles)
virtual QModelIndexsibling row, int column, const QModelIndex &index) const
virtual voidsort column, Qt::SortOrder order = Qt::AscendingOrder)
virtual QSizespan QModelIndex &index) const
virtual Qt::DropActionssupportedDragActions const
virtual Qt::DropActionssupportedDropActions const

公共槽函数

类型  函数名称
virtual voidrevert()
virtual boolsubmit()

信号

类型  函数名称
voidcolumnsAboutToBeInserted QModelIndex &parent, int first, int last)
voidcolumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
voidcolumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
voidcolumnsInserted(QModelIndex &parent, int first, int last)
voidcolumnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)
voidcolumnsRemoved(const QModelIndex &parent, int first, int last)
voiddataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector())
voidheaderDataChanged(Qt::Orientation orientation, int first, int last)
voidlayoutAboutToBeChanged(const QList &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint)
voidlayoutChanged(const QList &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint)
voidmodelAboutToBeReset()
voidmodelReset()
voidrowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
voidrowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
voidrowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
voidrowsInserted(const QModelIndex &parent, int first, int last)
voidrowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
voidrowsRemoved(const QModelIndex &parent, int first, int last)

受保护的函数

类型  函数名称
voidbeginInsertColumns(const QModelIndex &parent, int first, int last)
voidbeginInsertRows(const QModelIndex &parent, int first, int last)
boolbeginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
boolbeginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
voidbeginRemoveColumns(const QModelIndex &parent, int first, int last)
voidbeginRemoveRows(const QModelIndex &parent, int first, int last)
voidbeginResetModel()
voidchangePersistentIndex(const QModelIndex &from, const QModelIndex &to)
voidchangePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)
QModelIndexcreateIndex(int row, int column, void *ptr = nullptr) const
QModelIndexcreateIndex(int row, int column, quintptr id) const
voidendInsertColumns()
voidendInsertRows()
voidendMoveColumns()
voidendMoveRows()
voidendRemoveColumns()
voidendRemoveRows()
voidendResetModel()
QModelIndexListpersistentIndexList() const

受保护的槽函数

类型  函数名称
voidresetInternalData()

详细描述

QAbstractItemModel 类定义了项模型与模型/视图体系结构中的其他组件进行交互操作时必须使用的标准接口。应该子类化该类创建新的模型,而不是直接实例化使用。

QAbstractItemModel 类是模型/视图类中的一个,也是 Qt 模型/视图框架的一部分。它可以用作 QML 中的项视图元素或 Qt Widgets 模块中的项视图类的底层数据模型。

如果需要一个模型来使用项视图,比如 QMLList View 元素或者 C++ widgets 的 QListView 或者  QTableView,应该考虑子类化 QAbstractListModel 或者 QAbstractTableModel 而不是使用该类。

底层数据模型作为表的层次结构暴露给视图和委托。如果不使用层次结构,那么模型就是一个简单的具有行和列的表。每个项都有一个由 QModelIndex 指定的惟一索引。

modelindex-no-parent

每个数据项都可以通过包含一个关联的模型索引的模型进行访问。该索引可以通过 index() 函数获得。每个索引可能有一个 sibling() 索引;子项有一个 parent() 索引。

每个项目都有许多与之关联的数据元素,可以通过为模型的 data() 函数指定一个角色(请参阅 Qt::ItemDataRole)来检索它们。可以使用 itemData() 函数同时获取所有可用角色的数据。

使用特定的 Qt::ItemDataRole 设置每个角色的数据。可以使用 setData() 单独设置各个角色的数据,也可以使用 setItemData 设置所有角色的数据。

可以使用 flags() 查询项(请参阅 Qt::ItemFlag),以查看是否可以通过其他方式选择,拖动或操纵它们。

如果项具有子对象,则 hasChildren 为相应的索引返回 true

该模型在层次结构的每个级别都有一个 rowCount()columnCount。可以使用 insertRows()insertColumns()removeRows()removeColumns() 插入和删除行和列。

模型发出信号以指示变化。例如,只要模型可用的数据项发生更改,就会发出 dataChanged()。对模型提供的标题的更改将将发射 headerDataChanged() 信号。如果底层数据的结构发生了变化,则模型可以发出 layoutChanged() 来向任何附加的视图指示它们应该重新显示所显示的任何项,并需要考虑到新的结构。

可以使用 match() 函数在模型中搜索可用的项以查找特定数据。

要对模型进行排序,可以使用 sort()

子类化

注意: 在模型子类化参考中有一些关于模型子类化的通用指南。

子类化 QAbstractItemModel 时,至少必须实现 index()parent()rowCount()columnCount()data()。这些函数在所有的只读模型中使用,同样也构成了可编辑模型的基础。

还可以为模型重新实现 hasChildren() 来提供特殊的行为,而不是重新实现成本很高的 rowCount()。这使得模型可以限制视图请求的数据量,并且可以作为实现模型数据的惰性填充的一种方式。

要在模型中启用编辑,还必须实现 setData 和重新实现 flags() 以确保返回 ItemIsEditable。还可以重新实现 headerData()setHeaderData 来控制呈现模型标题的方式。

当分别重新实现 setData()setHeaderData() 函数时,必须显式发射 dataChanged()headerDataChanged() 信号。

定制模型需要创建模型索引以供其他组件使用。为此,请使用适当的行号和列号以及相应的标识符调用 createIndex(),并将其作为指针或整数值。这些值的组合对于每个项都必须是唯一的。定制模型通常在其他重新实现的函数中使用这些唯一标识符,以检索项数据并访问有关该项的父项和子项的信息。有关唯一标识符的更多信息,请参见简单树模型示例。

不必支持 Qt::ItemDataRole 中定义的每个角色。根据模型中包含的数据类型,可能只有实现 data() 函数以返回一些更常见角色的有效信息才有用。大多数模型至少为 Qt::DisplayRole 提供项数据的文本表示,行为良好的模型也应为 Qt::ToolTipRoleQt::WhatsThisRole 提供有效信息。支持这些角色可使模型与标准 Qt 视图一起使用。但是,对于某些处理高度专业化数据的模型,仅为用户定义的角色提供数据可能是合适的。

提供可调整数据结构大小的接口的模型可以提供 insertRows()removeRows()insertColumns()removeColumns() 的实现。在实现这些函数时,重要的是要在模型尺寸大小发生 之前之后 将有关模型尺寸的更改通知所有连接的视图:

这些函数发出的私有信号使附加组件有机会在任何数据变得不可用之前采取行动。使用这些 beginend 函数封装插入和删除操作还使模型能够正确地管理持久模型索引如果希望正确处理选择,则必须确保调用了这些函数。 如果插入或移除带有子项的项,则不需要为子项调用这些函数。换句话说,父项将管理其子项。

要创建增量填充的模型,可以重新实现 fetchMore()canFetchMore()。如果 fetchMore() 的重新实现向模型中添加了行,则必须调用 beginInsertRows()endInsertRows()

参见模型类模型子类化参考QModelIndexQAbstractItemView在项视图中使用拖放简单DOM模型示例简单树模型示例可编辑树模型示例Fetch More示例

成员类型文档

CheckIndexOption CheckIndexOptions

enum class QAbstractItemModel::CheckIndexOption flags QAbstractItemModel::CheckIndexOptions

这个枚举可以用来控制 QAbstractItemModel::checkIndex() 执行的检查。

| 常量 | 值 | 描述 | | ---- | ---- | ---- | ---- | | QAbstractItemModel::CheckIndexOption::NoOption | 0x0000 | 没有指定检查选项。| | QAbstractItemModel::CheckIndexOption::IndexIsValid | 0x0001 | 传递给 QAbstractItemModel::checkIndex() 的模型索引被检查为有效的模型索引。| | QAbstractItemModel::CheckIndexOption::DoNotUseParent | 0x0002 | 不执行任何涉及到传递给 QAbstractItemModel::checkIndex() 的父索引的使用的检查。| | QAbstractItemModel::CheckIndexOption::ParentIsInvalid | 0x0004 | 传递给 QAbstractItemModel::checkIndex() 的模型索引的父索引被检查为无效的模型索引。如果同时指定了此选项和 DoNotUseParent,则忽略此选项。|

该枚举是在 Qt 5.11 中引入或修改的。

CheckIndexOptions 类型是一个 QFlags<CheckIndexOption> 的类型定义。它存储一个或组合的 CheckIndexOption 值。

LayoutChangeHint

enum QAbstractItemModel::LayoutChangeHint

这个枚举描述了模型改变布局的方式。

常量描述
QAbstractItemModel::NoLayoutChangeHint0没有任何提示。
QAbstractItemModel::VerticalSortHint1正在对行进行排序。
QAbstractItemModel::HorizontalSortHint2正在对列进行排序。

注意,VerticalSortHint 和 HorizontalSortHint 表示项在同一父级中移动,而不是移动到模型中的不同父级,也没有过滤掉或过滤进来。

成员函数文档

QAbstractItemModel

QAbstractItemModel::QAbstractItemModel(QObject *parent = nullptr)

构造指定父类对象 parent 的抽象项模型。

columnsAboutToBeInserted

[ signal ] void QAbstractItemModel::columnsAboutToBeInserted(const QModelIndex &parent, int first, int last)

在将列插入模型之前就发射此信号。新项将位于给定父项 parent 下的首 firstlast之间。

注意: 连接到这个信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 的实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。它可以用于信号连接,但不能由用户发射。

参见 insertColumns()beginInsertColumns()

columnsAboutToBeMoved

[ signal ] void QAbstractItemModel::columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)

模型中的列被移动之前发射该信号。将要移动的项是在给定 sourceParent 下在 sourceStartsourceEnd 之间(包括首尾)的项。它们将从 destinationColumn 列开始移动到destinationParent

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt4.6 中被引入。

参见 beginMoveRows()。

columnsAboutToBeRemoved

[ signal ] void QAbstractItemModel::columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)

模型中的列被移除之前发射该信号。将要移除的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 removeColumns() 和 beginRemoveColumns()。

columnsInserted

[ signal ] void QAbstractItemModel::columnsInserted(const QModelIndex &parent, int first, int last)

将列插入到模型之后发射该信号。新的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 insertColumns() 和 beginInsertColumns()。

columnsMoved

[ signal ] void QAbstractItemModel::columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)

模型中的列被移动之后发射该信号。新的项是在给定 parent 下在 startend 之间(包括首尾)的项。它们将从 column 列开始移动到destination

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt4.6 中被引入。

参见 beginMoveRows()。

columnsRemoved

[ signal ] void QAbstractItemModel::columnsRemoved(const QModelIndex &parent, int first, int last)

模型中的列被移除之后发射该信号。移除的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 removeColumns() 和 beginRemoveColumns()。

dataChanged

[ signal ] void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector())

现有的项的数据发生改变时发射该信号。

如果项是同一父项,则受影响的项是在 topLeftbottomRight(包含)之间的项目。如果项没有相同的父项,则行为是不确定的。

当重新实现 setData() 函数时,必须显示地发射该信号。

可选的 roles 参数可用于指定实际修改了哪些数据角色。Roles 参数中的向量为空,表示应将所有角色视为已修改。角色参数中元素的顺序没有任何关联。

参见 headerDataChanged()、setData() 和 layoutChanged()。

headerDataChanged

[ signal ] void QAbstractItemModel::headerDataChanged(const Qt::Orientation &orientation, int first, int last)

当标题改变时发射该信号。orientation 表示是横向标题还是竖向标题发生了改变。标题中从 firstlast 的部分需要更新。

当重新实现 setData() 函数时,必须显示地发射该信号。

如果要更改列数或行数,则不需要发出此信号,而可以使用 begin/end 函数(有关详细信息,请参见 QAbstractItemModel 类描述中的子类化部分)。

参见 headerData()、setHeaderData() 和 dataChanged()。

layoutAboutToBeChanged

[ signal ] void QAbstractItemModel::layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint)

这个信号会在模型的布局改变之前发出。连接到这个信号的组件使用它来适应模型布局的变化。

在发出 layoutAboutToBeChanged() 之后,子类应该更新所有的持久化模型索引。

可选的 parents 参数用于提供更具体的通知关于模型布局的哪些部分正在被改变。空列表表示对整个模型的布局进行了更改。parents 列表中元素的顺序不重要。可选的 hint 参数用于提示模型重新布局时都发生了什么。

该函数在 Qt 5.0 中被引入。

参见 layoutChanged() 和 changePersistentIndex()。

layoutChanged

[ signal ] void QAbstractItemModel::layoutChanged(const QList<QPersistentModelIndex> &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint)

每当模型公开的项的布局发生变化时,就会发出这个信号,例如,对模型进行排序时。当视图接收到该信号时,应更新项的布局来反映此更改。

当对 QAbstractItemModelQAbstractProxyModel 进行子类化时,请确保在更改项顺序或更改要公开给视图的数据的结构之前发出 layoutAboutToBeChanged() 信号,并在更改布局后发出 layoutChanged() 信号。

可选的 parents 参数用于给出有关模型布局的哪些部分正在更改的具体的通知。空列表表示更改了整个模型的布局。parents 列表中元素的顺序并不重要。可选的 hint 参数用于提示模型重新布局时发生的情况。

子类应在发​​出 layoutChanged() 信号之前更新所有持久模型索引。换句话说,当结构改变时:

该函数在 Qt 5.0 中被引入。

参见 layoutAboutToBeChanged()、dataChanged()、headerDataChanged()、modelReset() 和 changePersistentIndex()。

modelAboutToBeReset

[ signal ] void QAbstractItemModel::modelAboutToBeReset()

当调用 beginResetModel() 时,在模型的内部状态(例如持久模型索引)失效之前发出这个信号。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt 4.2 中被引入。

参见 beginResetModel() 和 modelReset()。

modelReset

[ signal ] void QAbstractItemModel::modelReset()

当调用 endResetModel() 时,在模型的内部状态(例如持久模型索引)失效之后发出这个信号。

注意,如果模型被重置,则应该认为之前从模型中检索的所有信息都是无效的。这包括但不限于 rowCount()、columnCount()、flags()、通过 data()检索的数据和 roleNames()。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt 4.1 中被引入。

参见 endResetModel() 和 modelAboutToBeReset()。

resetInternalData

[ protected slot ] void QAbstractItemModel::resetInternalData()

该槽函数在模型的内部数据被清除并被重置之后被调用。

该槽函数为具体代理模型的子类提供了便利,例如维护了额外的数据的 QSortFilterProxyModel 的子类。

 class CustomDataProxy : public QSortFilterProxyModel
 {
     Q_OBJECT
 public:
     CustomDataProxy(QObject *parent)
       : QSortFilterProxyModel(parent)
     {
     }

     ...

     QVariant data(const QModelIndex &index, int role) override
     {
         if (role != Qt::BackgroundRole)
             return QSortFilterProxyModel::data(index, role);

         if (m_customData.contains(index.row()))
             return m_customData.value(index.row());
         return QSortFilterProxyModel::data(index, role);
     }

 private slots:
     void resetInternalData()
     {
         m_customData.clear();
     }

 private:
   QHash<int, QVariant> m_customData;
 };

注意: 由于错误,该槽函数没有出现在 Qt 5.0 中。

该函数在 Qt 4.8 中被引入。

参见 modelAboutToBeReset() 和 modelReset()。

revert

[ virtual slot ] void QAbstractItemModel::revert()

让模型知道它应该丢弃缓存的信息。这个函数通常用于行编辑。

该函数在 Qt 4.2 中被引入。

参见 submit()。

rowsAboutToBeInserted

[ signal ] void QAbstractItemModel::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)

在将行插入模型之前就发出该信号。新项将位于给定 parent 项目下的包含 startend 之间。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发出,而不能在子类代码中显式发出。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 insertRows() 和 beginInsertRows()。

rowsAboutToBeMoved

[ signal ] void QAbstractItemModel::rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)

模型中的行被移动之前发射该信号。将要移动的项是在给定 sourceParent 下在 sourceStartsourceEnd 之间(包括首尾)的项。它们将从 destinationRow 列开始移动到destinationParent

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt4.6 中被引入。

参见 beginMoveRows()。

rowsAboutToBeRemoved

[ signal ] void QAbstractItemModel::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)

模型中的行被移除之前发射该信号。将要移除的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 removeRows() 和 beginRemoveRows()。

rowsInserted

[ signal ] void QAbstractItemModel::rowsInserted(const QModelIndex &parent, int first, int last)

将行插入到模型之后发射该信号。新的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 insertRows() 和 beginInsertRows()。

rowsMoved

[ signal ] void QAbstractItemModel::rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)

模型中的行被移动之后发射该信号。新的项是在给定 parent 下在 startend 之间(包括首尾)的项。它们将从 column 列开始移动到destination

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

该函数在 Qt4.6 中被引入。

参见 beginMoveRows()。

rowsRemoved

[ signal ] void QAbstractItemModel::rowsRemoved(const QModelIndex &parent, int first, int last)

模型中的行被移除之后发射该信号。移除的项是在给定 parent 下在 firstlast 之间(包括首尾)的项。

注意: 连接到该信号的组件使用它来适应模型尺寸的变化。它只能由 QAbstractItemModel 实现发射,不能在子类代码中显式发射。

注意: 这是一个私有信号。仅用于信号连接,而不能由用户发射。

参见 removeRows() 和 beginRemoveRows()。

submit

[ virtual slot ] void QAbstractItemModel::submit()

让模型知道它应该将缓存的信息提交到永久存储。这个函数通常用于行编辑。

如果没有错误,返回 true;否则返回 false

参见 revert()。

~QAbstractItemModel

[ virtual ] void QAbstractItemModel::~QAbstractItemModel()

销毁抽象项模型。

beginInsertColumns

[ protected ] void QAbstractItemModel::beginInsertColumns(const QModelIndex &parent, int first, int last)

开始一个列插入操作。

在子类中重新实现 insertColumns() 时,必须在将数据插入模型的底层数据存储之前调用此函数。parent 索引对应于插入新列的父索引;firstlast 是新列插入后的列号。

Inserting columns指定要插入到模型项中的列的范围的第一个和最后一个列号。

例如,如图所示,我们在列4之前插入三列,所以 first 是4,last 是 6:

beginInsertColumns(parent, 4, 6);

这将插入三个新列作为列4、5和6。

Appending columns要追加列,请将它们插入到最后一列之后。例如,如图所示,我们将三列附加到一个包含六列的集合(以列5结尾),因此 first 是 6 and last 是 8:

beginInsertColumns(parent, 6, 8);

这将追加两个新列作为列6、7和8。

注意: 此函数发出 columnAboutToBeInserted() 信号,在插入数据之前,已连接的视图(或代理)必须处理该信号。否则,视图可能会以无效状态结束。

参见 endInsertColumns()。

beginInsertRows

[ protected ] void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)

开始一个行插入操作。

在子类中重新实现 insertRows() 时,必须在将数据插入模型的底层数据存储之前调用此函数。parent 索引对应于插入新列的父索引;firstlast 是新行插入后的行号。

Inserting rows为要插入模型中项的行范围指定第一行和最后一行。

例如,如图所示,我们在第2行之前插入三行,因此first 是2,first 是4:

beginInsertRows(parent, 2, 4);

这将插入三行新行,即第2、3和4行。

Appending rows要追加行,请将它们插入到最后一行之后。例如,如图所示,我们将两行附加到一个包含4个现有行的集合(以第3行结束),因此 first 是4,last 是5:

beginInsertRows(parent, 4, 5);

这将追加两个新行作为第4行和第5行。

注意: 此函数发出 rowsAboutToBeInserted() 信号,在插入数据之前,已连接的视图(或代理)必须处理该信号。否则,视图可能会以无效状态结束。

参见 endInsertRows()。

beginMoveColumns

[ protected ] void QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)

开始一个列移动操作。

当重新实现子类时,此方法简化了模型中实体的移动。此方法负责在模型中移动持久索引,否则您将需要自己执行此操作。使用 beginMoveColumnsendMoveColumns() 是直接发送与 changePersistentIndex() 一起的 layoutAboutToBeChanged() 和 layoutChanged() 的另一种选择。

sourceParent 索引对应于从其移出列的父级;sourceFirstsourceLast 是要移动的列的第一列和最后一列。destinationParent 索引对应于将这些列移入的父级。destinationChild 是要将列移动到的列。也就是说,sourceParentsourceFirst 列的索引将成为 destinationParent 中的 destinationChild 列,然后是所有其他列,直到 sourceLast

但是,当在同一父目录下移动列时(sourceParentdestinationParent 是相等的),这些列将被放置在 destinationChild 索引之前。也就是说,如果您希望移动列0和1,使它们变成列 1 和列 2,destinationChild 应该是 3。在本例中,源列 i (位于 sourceFirstsourceLast 之间)的新索引等于(destinationChild-sourceLast-1+i)。

注意,如果 sourceParentdestinationParent 是相同的,您必须确保 destinationChild 不在 sourceFirstsourceLast + 1 的范围内。还必须确保不会尝试将列移动到它自己的子列或祖先列中。如果任一条件为真,此方法将返回 false,在这种情况下,应中止移动操作。

该函数在 Qt4.6 中被引入。

参见 endMoveColumns()。

beginMoveRows

[ protected ] void QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)

开始一个行移动操作。

当重新实现子类时,此方法简化了模型中实体的移动。此方法负责在模型中移动持久索引,否则您将需要自己执行此操作。使用 beginMoveRowsendMoveRows 是直接发送与 changePersistentIndex() 一起的 layoutAboutToBeChanged() 和 layoutChanged() 的另一种选择。

sourceParent 索引对应于从其移出行的父级;sourceFirstsourceLast 是要移动的行的第一行和最后一行。destinationParent 索引对应于将这些行移入的父级。destinationChild 是要将行移动到的行。也就是说,sourceParent 中的 sourceFirst 行的索引将成为 destinationParent 中的 destinationChild 行,然后是所有其他行,直到 sourceLast

但是,当在同一父目录下移动列时(sourceParentdestinationParent 是相等的),这些行将被放置在 destinationChild 索引之前。也就是说,如果您希望移动列0和1,使它们变成行 1 和行 2,destinationChild 应该是 3。在本例中,源行 i (位于 sourceFirstsourceLast 之间)的新索引等于(destinationChild-sourceLast-1+i)。

注意,如果 sourceParentdestinationParent 是相同的,您必须确保 destinationChild 不在 sourceFirstsourceLast + 1 的范围内。还必须确保不会尝试将行移动到它自己的子列或祖先行中。如果任一条件为真,此方法将返回 false,在这种情况下,应中止移动操作。

Moving rows to another parent指定源父行中您希望在模型中移动的行跨度的第一行和最后一行编号。还要在目标父级中指定要将范围内的行移动到的行。例如,如图所示,我们将源中的第 2 行到第 3 行移动了三行,因此 sourceFirst 为 2,sourceLast 为 4。我们将这些项移动到目标的第2行上方,因此 destinationChild 为2。

beginMoveRows(sourceParent, 2, 4, destinationParent, 2);

这会将源中的三行第 2、3 和 4 行移动到目标中的 2、3 和 4 行。其他受影响的同级项也因此被移位。

Moving rows to append to another parent若要将行追加到另一个父元素,请将它们移到最后一行的后面。例如,如图所示,我们将三行移动到一个包含 6 个现有行的集合中(以第 5 行结束),因此 destinationChild 为6:

beginMoveRows(sourceParent, 2, 4, destinationParent, 6);

这会将目标行移到目标父级的末尾,分别为 6、7 和 8。

Moving rows in the same parent up要在同一父级中移动行,请指定要将其移动到的行。 例如,如图所示,我们将一项从第 2 行移至第 0 行,因此 sourceFirstsourceLast 为2,destinationChild 为0。

beginMoveRows(parent, 2, 2, parent, 0);

注意,其他行可能会相应移位。另请注意,在同一父级中移动项时,请勿尝试无效移动或无操作移动。在上面的示例中,项 2 位于移动之前的第 2 行,因此无法将其移动到第 2 行(已经存在)或第 3 行(空操作,因为第 3 行意味着已经在第 3 行之上)

Moving rows in the same parent down要在同一父级中移动行,请指定要将其移动到的行。例如,如图所示,我们将一项从第 2 行移至第 4 行,因此 sourceFirstsourceLast 为2,destinationChild 为4。

beginMoveRows(parent, 2, 2, parent, 4);

注意,其他行可能会相应移位。

该函数在 Qt4.6 中被引入。

参见 endMoveRows()。

beginRemoveColumns

[ protected ] void QAbstractItemModel::beginRemoveColumns(const QModelIndex &parent, int first, int last)

开始一个列移除操作。

在子类中重新实现 removeColumns() 时,必须在从模型的底层数据存储中删除数据之前调用此函数。parent 索引对应于删除新列的父索引; firstlast 是要删除的第一个和最后一个列的列号。

注意: 此函数发出 columnAboutToBeRemoved() 信号,在删除数据之前,已连接的视图(或代理)必须处理该信号。否则,视图可能会以无效状态结束。

参见 endRemoveColumns()。

Removing columns指定要从模型中的项中删除的列的范围的第一个和最后一个列号。例如,如图所示,我们将这三列从第4列移到第6列,因此 first 是4,last 是6:

beginRemoveColumns(parent, 4, 6);

beginRemoveRows

[ protected ] void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)

开始一个行移除操作。

在子类中重新实现 removeRows() 时,必须在从模型的基础数据存储中删除数据之前调用此函数。

parent 引对应于从中删除新行的父索引;firstlast 是要删除的行的行号。

Removing rows指定要从模型中的项中删除的行范围的第一个和最后一个行号。例如,如图所示,我们将从第 2 行到第 3 行的两行删除,因此 first 是 2,last 是 3:

beginRemoveRows(parent, 2, 3);

注意: 此函数发出 rowsAboutToBeRemoved() 信号,连接的视图(或代理)必须在删除数据之前处理该信号。否则,视图可能会以无效状态结束。

参见 endRemoveRows()。

beginResetModel

[ protected ] void QAbstractItemModel::beginResetModel()

开始模型重置操作。

重置操作会在任何附加的视图中将模型重置为当前状态。

注意: 附加到这个模型的任何视图都将被重置。

当一个模型被重置时,这意味着以前从该模型报告的任何数据现在都是无效的,必须再次进行查询。这也意味着当前项和任何选定项都将无效。当模型从根本上更改其数据时,有时只需调用此函数比在底层数据源或其结构发生更改时发出 dataChanged() 通知其他组件更容易。

在重新设置模型或代理模型中的任何内部数据结构之前,必须调用此函数。

这个函数发出信号 modelAboutToBeReset()。

该函数在 Qt4.6 中被引入。

参见 modelAboutToBeReset()、modelReset() 和 endResetModel()。

buddy

[ virtual ] void QAbstractItemModel::buddy(const QModelIndex &index) const

返回由 index 表示的项的伙伴的模型索引。当用户想要编辑项目时,视图将调用此函数以检查是否应改为编辑模型中的另一个项。然后,视图将使用伙伴项返回的模型索引构造一个委托。

此功能的默认实现将每个项都作为自己的伙伴。

canDropMimeData

[ virtual ] bool QAbstractItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const

如果模型接受放置 data,则返回 true。这个默认实现只检查 mimeTypes() 列表中数据是否至少有一种格式,以及操作是否在模型的 supportedDropActions() 中。

如果您想要测试是否可以在 rowcolumnparent节点上放置 data,请在自定义模型中重新实现此函数。如果您不需要该测试,那么就没有必要重新实现此函数。

参见 dropMimeData() 和 在项视图中使用拖放

canFetchMore

[ virtual ] bool QAbstractItemModel::canFetchMore(const QModelIndex &parent) const

如果在 parent 索引下有更多可用的数据返回 true;否则返回 fasle;

默认的实现总是返回 false

如果 canFetchMore() 返回 true,则应该调用 fetchMore() 函数。比如 QAbstractItemView 就是这样做的。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 fetchMore()。

changePersistentIndex

[ protected ] void QAbstractItemModel::changePersistentIndex(const QModelIndex &from, const QModelIndex &to)

将等于给定的 fromQPersistentModelIndex() 模型索引更改为 to 模型索引。

如果没有找到与给定的模型索引 from 相等的持久模型索引,则什么也不会改变。

如果 canFetchMore() 返回 true,则应该调用 fetchMore() 函数。比如 QAbstractItemView 就是这样做的。

参见 persistentIndexList() 和 changePersistentIndexList()。

changePersistentIndexList

[ protected ] void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)

将等于给定的 fromQPersistentModelIndex()es 模型索引列表更改为 to 模型索引列表。

如果没有找到与给定的模型索引 from 相等的持久模型索引,则什么也不会改变。

该函数在 Qt4.1 中被引入。

参见 persistentIndexList() 和 changePersistentIndex()。

checkIndex

bool QAbstractItemModel::checkIndex(const QModelIndex &index, QAbstractItemModel::CheckIndexOptions options = CheckIndexOption::NoOption) const

此函数检查索引是否为此模型的合法模型索引。 合法模型索引要么是无效的模型索引,要么是具有以下所有条件的有效模型索引:

  • index 的模型就是 this
  • index 的行数大于等于零;
  • index 的行数小于父索引的行数;
  • index 的列数大于等于零;
  • index 的列数小于父索引的列数。

options 参数可能会改变其中一些检查。如果 options 包含 IndexIsValid,那么 index 必须是一个有效的索引;这在重新实现 data() 或 setData() 等需要有效索引的函数时非常有用。

如果 options 包含 DoNotUseParent,那么将调用 parent() 的检查将被省略;允许在重新实现的 parent() 函数中调用此函数(否则,将导致无穷递归和崩溃)。

如果 options 不包含 DoNotUseParent,但包含 IndexIsValid,那么将执行额外的检查:检查父索引是否有效。这在实现平面模型(如列表或表)时非常有用,在这种情况下,模型索引不应该具有有效的父索引。

该函数如果检查成功返回 true,否则返回 false。允许在 Q_ASSERT 和类似的其他调试机制中使用该函数。如果某些检查失败,则将在 qt.core.qabstractitemmodel.checkindex 日志记录类别中显示一条警告消息,其中包含一些可能对调试失败有用的信息。

注意: 这个函数是一个调试助手,用于实现您自己的项模型。在开发复杂模型时,以及在构建复杂的模型层次结构时(例如使用代理模型),调用这个函数来捕获传递给某个 QAbstractItemModel() API 的非法模型索引(如上定义)相关的bug是很有用的。

警告: 请注意,将非法索引传递给项模型是未定义的行为,因此应用程序必须避免这样做,并且不能依赖于项模型可以用来优雅地处理非法索引的任何“防御性”编程。

该函数在 `Qt5.11 中被引入。

参见 QModelIndex

columnCount

[ pure virtual ] int QAbstractItemModel::columnCount(const QModelIndex &parent = QModelIndex()) const

返回给定 parent 索引的子项的列的数量。

在大多数子类中,列的数量独立于 parent

例如:

 int DomModel::columnCount(const QModelIndex &parent) const
 {
     Q_UNUSED(parent);
     return 3;
 }

注意: 在实现基于表的模型时,当父模型有效时,columnCount() 应该返回 0。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

该函数在 Qt4.1 中被引入。

参见 rowCount()。

createIndex

[ protected ] QModelIndex QAbstractItemModel::createIndex(int row, int column, void *ptr = nullptr) const

使用内部指针 ptr 为给定的 rowcolumn 创建模型索引。

当使用 QSortFilterProxyModel 时,它的索引有自己的内部指针。不建议在模型外部访问这个内部指针。使用 data() 函数代替。

这个函数提供了一个一致的接口,模型子类必须使用这个接口来创建模型索引。

参见 QModelIndex::internalId()。

data

[ pure virtual ] QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const

返回指定角色 role 和 索引 index 的项数据。

注意: 如果没有要返回的值,则返回无效的 QVariant,而不是返回 0。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 Qt::ItemDataRolesetData() 和 headerData()。

dropMimeData

[ virtual ] bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const

处理以给定操作 action 结束的拖放操作提供的数据 data

如果数据和操作被模型处理了则返回 true,否则返回 false

指定的行 row、列 column 和父索引 parent 指示模型中操作结束的项的位置。在正确的位置完成动作是模型的责任。

例如,QTreeView 中的一个项上的拖放操作可以导致新项作为行 row、列 column 和父索引 parent 指定的项的子项插入,或者作为项的兄弟项插入。

当行 row 和列 column 为 -1 时,这意味着放置的数据应该被认为是直接在 parent 上放置的。通常这意味着将数据附加为父项 parent 的子项。如果行 row 和列 column 大于或等于零,则表示放置发生在指定父索引 parentrow 和列 column 的前面。

调用 mimeTypes() 成员来获取可接受的 MIME 类型列表。这个默认实现假定 mimeTypes() 是默认实现,它返回一个默认 MIME 类型。如果您在自定义模型中重新实现 mimeTypes() 以返回多个 MIME 类型,那么您必须重新实现此函数以使用它们。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 supportedDropActionscanDropMimeData() 和 在项视图中使用拖放

endInsertColumns

[ protected ] void QAbstractItemModel::endInsertColumns()

结束列插入操作。

在子类中重新实现 insertColumns()时,必须在将数据插入模型的底层数据存储之后调用此函数。

参见 beginInsertColumns()。

endInsertRows

[ protected ] void QAbstractItemModel::endInsertRows()

结束行插入操作。

在子类中重新实现 insertRows()时,必须在将数据插入模型的底层数据存储之后调用此函数。

参见 beginInsertRows()。

endMoveColumns

[ protected ] void QAbstractItemModel::endMoveColumns()

结束列移动操作。

在实现子类时,必须在模型的底层数据存储中移动数据之后调用此函数。

该函数在 Qt4.6 中被引入。

参见 beginMoveColumns()。

endMoveRows

[ protected ] void QAbstractItemModel::endMoveRows()

结束行移动操作。

在实现子类时,必须在模型的底层数据存储中移动数据之后调用此函数。

该函数在 Qt4.6 中被引入。

参见 beginMoveRows()。

endRemoveColumns

[ protected ] void QAbstractItemModel::endRemoveColumns()

结束列删除操作。

在子类中重新实现 removeColumns() 时,必须在从模型的底层数据存储中删除数据之后调用此函数。

参见 beginRemoveColumns()。

endRemoveRows

[ protected ] void QAbstractItemModel::endRemoveRows()

结束行删除操作。

在子类中重新实现 removeRows() 时,必须在从模型的底层数据存储中删除数据之后调用此函数。

参见 beginRemoveRows()。

endResetModel

[ protected ] void QAbstractItemModel::endResetModel()

完成模型重置操作。

在重置模型或代理模型中的任何内部数据结构后,必须调用此函数。

该函数发出 modelReset() 信号。

该函数在 Qt4.6 中被引入。

参见 beginResetModel()。

fetchMore

[ virtual ] void QAbstractItemModel::fetchMore(const QModelIndex &parent)

获取指定的 parent 父索引的项的任何可用的数据。

如果递增地填充模型,则需要重新实现该函数。

该函数的默认实现没有做任何事情。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 canFetchMore()。

flags

[ virtual ] Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const

返回给定索引的项标志。

基类的实现返回启用项(ItemIsEnabled)和允许选择项(ItemIsSelectable)的标志的组合。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 Qt::ItemFlags

hasChildren

[ virtual ] Qt::ItemFlags QAbstractItemModel::hasChildren(const QModelIndex &parent = QModelIndex()) const

如果父索引 parent 有任何子项则返回 true,否则返回 false

在父索引上使用 rowCount() 来查找子项的数量。

注意,如果一个索引设置了 Qt::ItemNeverHasChildren 标志,那么用该索引调用该方法是未定义的行为。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 parent() 和 index()。

hasIndex

[ virtual ] bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const

如果模型返回一个指定父索引 parent、行 row 和列 column 的有效 QModelIndex,则返回 true,否则返回 false

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

headerData

[ virtual ] QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const

返回标题中具有给定 orientationsection 的数据。

对于水平标题,节号对应于列号。类似地,对于垂直标题,节号对应于行号。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 Qt::ItemDataRolesetHeaderData() 和 QHeaderView

index

[ pure virtual ] QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const

返回模型中指定 rowcolumnparent 索引的项的索引。

在子类中重新实现此函数时,调用 createIndex() 来生成模型索引,其他组件可以使用这些索引来引用模型中的项。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 createIndex()。

insertColumn

bool QAbstractItemModel::insertColumn(int column, const QModelIndex &parent = QModelIndex()) const

在指定 parent 索引的子项的指定 column 之前插入一列。

如果插入了该列,则返回 true;否则,返回 false

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 insertColumns()、insertRow() 和 removeColumn()。

insertColumns

[ virtual ] bool QAbstractItemModel::insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) const

在支持此功能的模型上,在模型中的给定 column 之前插入 count 列新列。每个新列中的项将是由父模型索引 parent 表示的项的子项目。

如果 column 为 0,则这些列将添加到任何现有列的前面。

如果 columncolumnCount(),则将这些列追加到任何现有列之后。

如果 parent 没有子项,插入带有 count 列的单行。

如果列成功插入,则返回 true,否则返回 false

基类的实现没有做任何事情,并且返回 false

如果您实现了自己的模型,希望支持插入,则可以重新实现此函数。或者,您可以提供自己的 API 来更改数据。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 insertRows()、removeColumns()、beginInsertColumns() 和 endInsertColumns()。

insertRow

bool QAbstractItemModel::insertRow(int row, const QModelIndex &parent = QModelIndex()) const

在指定 parent 索引的子项的指定 row 之前插入一列。

注意: 该函数调用了虚函数 insertRows()。

如果插入了该行,则返回 true;否则,返回 false

参见 insertRows()、insertColumn() 和 removeRow()。

insertRows

[ virtual ] bool QAbstractItemModel::insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) const

注意: 基类的实现没有做任何事情,并且返回 false

在支持此功能的模型上,将 count 行插入模型中给定的行之前。新行中的项将是由父模型索引 parent 表示的项的子项。

如果 row 为 0,则这些行将添加到任何现有列的前面。

如果 rowrowCount(),则将这些列追加到任何现有行之后。

如果 parent 没有子项,插入带有 count 行的单列。

如果列成功插入,则返回 true,否则返回 false

如果您实现了自己的模型,希望支持插入,则可以重新实现此函数。或者,您可以提供自己的 API 来更改数据。在任何一种情况下,您都需要调用 beginInsertRows() 和 endInsertRows() 来通知其他组件模型已经更改

参见 insertColumns()、removeRows()、beginInsertRows() 和 endInsertRows()。

itemData

[ virtual ] QMap<int, QVariant> QAbstractItemModel::itemData(const QModelIndex &index) const

为给定索引 index 处的项返回具有模型中所有预定义角色值的 map

如果希望扩展此函数的默认行为以在 map 中包含自定义角色,请重新实现此函数。

参见 setItemData()、Qt::ItemDataRoledata()。

match

[ virtual ] QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const

返回一列项的索引,这些索引在 start 索引的列中并且该索引下的数据在给定角色下存储的数据与指定值匹配。执行搜索的方式由给定的 flags 定义。返回的列表可能是空的。还要注意,如果使用了代理模型,列表中结果的顺序可能与模型中的顺序不一致。不能依赖结果的顺序。

搜索从 start 索引开始,直到匹配数据项的数量等于 hits,搜索到达最后一行,或者再次搜索到达start—这取决于是否在 flags 中指定了 MatchWrap。如果希望搜索所有匹配项,请使用 hits = -1

默认情况下,此函数将对所有项执行基于字符串的包装比较,搜索以 value 指定的搜索项开头的项。

注意: 这个函数的默认实现只搜索列。重新实现此函数以包含不同的搜索行为。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

mimeData

[ virtual ] QMimeData QAbstractItemModel::mimeData(const QModelIndexList &indexes) const

返回一个对象,该对象包含与指定索引 indexes 列表对应的序列化数据项。用于描述编码数据的格式是从 mimeTypes() 函数获得的。这个默认实现使用 mimeTypes() 的默认实现返回的默认 MIME 类型。如果您在自定义模型中重新实现 mimeTypes() 以返回更多 MIME 类型,那么重新实现此函数以使用它们。

如果 indexes 为空,或者没有受支持的 MIME 类型,则返回 0,而不是序列化的空列表。

参见 mimeTypes() 和 dropMimeData()。

mimeTypes

[ virtual ] QStringList QAbstractItemModel::mimeTypes() const

返回允许的 MIME 类型的列表。默认情况下,内置模型和视图使用内部 MIME 类型:application / x-qabstractitemmodeldatalist

在自定义模型中实现拖放支持时,如果您将以默认内部 MIME 类型以外的格式返回数据,请重新实现此函数以返回您的 MIME 类型列表。

如果在自定义模型中重新实现这个函数,还必须重新实现调用它的成员函数: mimeData() 和 dropMimeData()。

参见 mimeData() 和 dropMimeData()。

moveColumn

bool QAbstractItemModel::moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild)

在支持此功能的模型上,将 sourceColumn从sourceParent 移到 destinationParent 下的 destinationChild

如果列被成功移动,则返回 true;否则返回 false

参见 moveColumns() 和 moveRow()。

moveColumns

[ virtual ] bool QAbstractItemModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild)

在支持此功能的模型上,将 count 列从父索引 sourceParent 下的给定 sourceColumn 移到父索引 destinationParent 下的 destinationChild 列。

如果列被成功移动,则返回 true;否则返回 false

基类的实现没有做任何事情,并且返回 false

如果实现自己的模型,则如果要支持移动,则可以重新实现此功能。另外,您可以提供自己的 API 来更改数据。

参见 beginMoveColumns() 和 endMoveColumns()。

moveRow

bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow const QModelIndex &destinationParent, int destinationChild)

在支持此功能的模型上,将 sourceColumn从sourceParent 移到 destinationParent 下的 destinationChild

如果行被成功移动,则返回 true;否则返回 false

参见 moveRows() 和 moveColumn()。

moveRows

[ virtual ] bool QAbstractItemModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)

在支持此功能的模型上,将 count 行从父索引 sourceParent 下的给定 sourceColumn 移到父索引 destinationParent 下的 destinationChild 行。

如果行被成功移动,则返回 true;否则返回 false

基类的实现没有做任何事情,并且返回 false

如果实现自己的模型,则如果要支持移动,则可以重新实现此功能。另外,您可以提供自己的 API 来更改数据。

参见 beginMoveRows() 和 endMoveRows()。

parent

[ pure virtual ] bool QAbstractItemModel::parent(const QModelIndex &index) const

返回具有给定索引 index 的模型项的父项。如果该项没有父项,则返回无效的 QModelIndex

在公开树数据结构的模型中使用的常见约定是,只有第一列中的项才有子级。对于这种情况,当在子类中重新实现此函数时,返回的 QModelIndex 的列将为0。

在子类中重新实现这个函数时,要小心避免调用 QModelIndex 成员函数,比如 QModelIndex::parent(),因为模型的索引将简单地调用实现,从而导致无限递归。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 createIndex()。

persistentIndexList

[ protected ] QModelIndexList QAbstractItemModel::persistentIndexList() const

返回作为模型中的持久索引存储的索引列表。

该函数在 Qt4.2 中被引入。

removeColumn

bool QAbstractItemModel::removeColumn(int column, const QModelIndex &parent = QModelIndex())

从指定的父项 parent 的子项中删除给定的列 column

如果删除了该列,则返回 true;否则返回 false

参见 removeColumns()、removeRow()和insertColumn()。

removeColumns

[ virtual ] bool QAbstractItemModel::removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())

在支持此功能的模型上,从模型中删除以父项 parent 下给定列 column 开头的 count 列。

如果列被成功删除,返回头 true;否则返回 false

基类的实现没有做任何事情并返回了 false

如果实现自己的模型,要支持删除,则可以重新实现此函数。 另外,您可以提供自己的 API 来更改数据。

参见 removeColumn()、removeRows()、insertColumns()、beginRemoveColumns() 和 endRemoveColumns()。

removeRow

bool QAbstractItemModel::removeRow(int row, const QModelIndex &parent = QModelIndex())

从指定的父项 parent 的子项中删除给定的行 row

如果删除了该行,则返回 true;否则返回 false

这是一个调用 removeRows()的便利函数。QAbstractItemModelremoveRows()的实现不做任何事情。

参见 removeRows()、removeColumn()和insertRow()。

removeRows

[ virtual ] bool QAbstractItemModel::removeRows(int row, int count, const QModelIndex &parent = QModelIndex())

在支持此功能的模型上,从模型中删除以父项 parent 下给定列 row 开头的 count 行。

如果行被成功删除,返回头 true;否则返回 false

基类的实现没有做任何事情并返回了 false

如果实现自己的模型,要支持删除,则可以重新实现此函数。 另外,您可以提供自己的 API 来更改数据。

参见 removeRow()、removeColumns()、insertColumns()、beginRemoveRows() 和 endRemoveRows()。

roleNames

[ virtual ] QHash<int, QByteArray> QAbstractItemModel::roleNames() const

返回模型的角色名称。

Qt 设置的默认角色名是:

Qt RoleQML Role Name
Qt::DisplayRoledisplay
Qt::DecorationRoledecoration
Qt::EditRoleedit
Qt::ToolTipRoletoolTip
Qt::StatusTipRolestatusTip
Qt::WhatsThisRolewhatsThis

参见 removeRow()、removeColumns()、insertColumns()、beginRemoveRows() 和 endRemoveRows()。

该函数在 Qt4.6 中被引入。

参见 setRoleNames()。

rowCount

[ pure virtual ] int QAbstractItemModel::rowCount(const QModelIndex &parent = QModelIndex()) const

返回给定父节点 parent 下的行数。当父节点有效时,这意味着 rowCount 返回父节点的子节点数。

注意: 在实现基于表的模型时,当父节点有效时,rowCount() 应该返回 0。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 columnCount()。

setData

[ virtual ] bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

将索引 index 处的项的角色数据设置为 value

成功返回 true;否则返回 false

如果数据被成功设置,应该发出 dataChanged() 信号。

基类的实现返回 false。对于可编辑的模型来说,该函数和 data() 必须被实现。

**注意:**该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 Qt::ItemDataRoledata() 和 itemData()。

setHeaderData

[ virtual ] bool QAbstractItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)

设置指定 sectionorientationrole 标题的数据为 value

标题数据更新完成,返回 true;否则返回 false

在重新实现此函数时,必须显式发出 headerDataChanged() 信号。

注意: 该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 Qt::ItemDataRoleheaderData()。

setItemData

[ virtual ] bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)

对于每个 Qt::ItemDataRole,将索引 index 处的项目的角色数据设置为角色中的关联值。

设置成功,返回 true;否则返回 false

不在角色中的角色将不会被修改。

参见 setData()、data() 和 itemData()。

sibling

[ virtual ] QModelIndex QAbstractItemModel::sibling(int row, int column, const QModelIndex &) const

返回索引 index 项的行和列上的同级索引,如果该位置上没有同级索引,则返回无效的 QModelIndex

sibling() 只是一个便捷函数,它找到项的父项,并使用它来检索指定行和列中子项的索引。

可以选择性地重写此方法以进行特定于实现的优化。

**注意:**该函数可以通过元对象系统和 QML 调用。请参阅 Q_INVOKABLE

参见 index()、QModelIndex::row() 和 QModelIndex::column()。

sort

[ virtual ] void QAbstractItemModel::sort(int column, Qt::SortOrder order = Qt::AscendingOrder)

按给定顺序 order 按列 column 对模型进行排序。

基类实现不执行任何操作。

span

[ virtual ] QSize QAbstractItemModel::span(const QModelIndex &index) const

返回由索引 index 表示的项的行和列跨度。

注意: 目前没有使用span。

supportedDragActions

[ virtual ] Qt::DropActions QAbstractItemModel::supportedDragActions() const

返回此模型中数据支持的操作。

默认实现返回 supportedDropActions()。如果希望支持其他操作,请重新实现此函数。

当发生拖动时,QAbstractItemView::startDrag() 使用 supportedDragActions() 作为默认值。

注意: 目前没有使用span。

参见 setSupportedDragActions()、Qt::DropActions在项视图中使用拖放

supportedDropActions

[ virtual ] Qt::DropActions QAbstractItemModel::supportedDropActions() const

返回此模型支持的放置动作。

默认实现返回 Qt::CopyAction。如果希望支持其他操作,请重新实现此函数。您还必须重新实现 dropMimeData() 函数来处理额外的操作。

该函数在 Qt4.2 中被引入。

参见 dropMimeData()、Qt::DropActions在项视图中使用拖放

[TOC]

QAbstractSocket Class

QAbstractSocket 类是Qt中 Socket 通信类的基类,被 QTcpSocketQUdpSocket等类继承。QAbstractSocket 类为所有的socket通信类提供了最基本的功能。

属性方法
头文件#include <QAbstractSocket>
qmake参数QT += network
父类QIODevice
子类QTcpSocketQUdpSocket

公共成员类型

类型方法
enumBindFlag { ShareAddress, DontShareAddress, ReuseAddressHint, DefaultForPlatform }
flagsBindMode
enumNetworkLayerProtocol{ IPv4Protocol, IPv6Protocol, AnyIPProtocol, UnknownNetworkLayerProtocol }
enumPauseMode { PauseNever, PauseOnSslErrors }
flagsPauseModes
enumSocketError { ConnectionRefusedError, RemoteHostClosedError, HostNotFoundError, SocketAccessError, SocketResourceError, …, UnknownSocketError }
enumSocketOption{ LowDelayOption, KeepAliveOption, MulticastTtlOption, MulticastLoopbackOption, TypeOfServiceOption, …, PathMtuSocketOption }
enumSocketState { UnconnectedState, HostLookupState, ConnectingState, ConnectedState, BoundState, …, ListeningState }
enumSocketType { TcpSocket, UdpSocket, SctpSocket, UnknownSocketType }

公共成员函数

类型函数名
QAbstractSocket(QAbstractSocket::SocketType socketType, QObject *parent)
virtual~QAbstractSocket()
voidabort()
boolbind(const QHostAddress &address, quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
boolbind(quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
virtual voidconnectToHost(const QString &hostName, quint16 port, QIODevice::OpenMode openMode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
virtual voidconnectToHost(const QHostAddress &address, quint16 port, QIODevice::OpenMode openMode = ReadWrite)
virtual voiddisconnectFromHost()
QAbstractSocket::SocketErrorerror() const
boolflush()
boolisValid() const
QHostAddresslocalAddress() const
quint16localPort() const
QAbstractSocket::PauseModespauseMode() const
QHostAddresspeerAddress() const
QStringpeerName() const
quint16peerPort() const
QStringprotocolTag() const
QNetworkProxyproxy() const
qint64readBufferSize() const
virtual voidresume()
voidsetPauseMode(QAbstractSocket::PauseModes pauseMode)
voidsetProtocolTag(const QString &tag)
voidsetProxy(const QNetworkProxy &networkProxy)
virtual voidsetReadBufferSize(qint64 size)
virtual boolsetSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = ConnectedState, QIODevice::OpenMode openMode = ReadWrite)
virtual voidsetSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
virtual qintptrsocketDescriptor() const
virtual QVariantsocketOption(QAbstractSocket::SocketOption option)
QAbstractSocket::SocketTypesocketType() const
QAbstractSocket::SocketStatestate() const
virtual boolwaitForConnected(int msecs = 30000)
virtual boolwaitForDisconnected(int msecs = 30000)

重载公共成员函数

类型函数名
virtual boolatEnd() const override
virtual qint64bytesAvailable() const override
virtual qint64bytesToWrite() const override
virtual boolcanReadLine() const override
virtual voidclose() override
virtual boolisSequential() const override
virtual boolwaitForBytesWritten(int msecs = 30000) override
virtual boolwaitForReadyRead(int msecs = 30000) override

信号

类型函数名
voidconnected()
voiddisconnected()
voiderrorOccurred(QAbstractSocket::SocketError socketError)
voidhostFound()
voidproxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
voidstateChanged(QAbstractSocket::SocketState socketState)

保护成员函数

类型函数名
voidsetLocalAddress(const QHostAddress &address)
voidsetLocalPort(quint16 port)
voidsetPeerAddress(const QHostAddress &address)
voidsetPeerName(const QString &name)
voidsetPeerPort(quint16 port)
voidsetSocketError(QAbstractSocket::SocketError socketError)
voidsetSocketState(QAbstractSocket::SocketState state)

重载保护成员函数

类型函数名
virtual qint64readData(char *data, qint64 maxSize) override
virtual qint64readLineData(char *data, qint64 maxlen) override
virtual qint64writeData(const char *data, qint64 size) override

详细介绍

QAbstractSocket 类是 QTcpSocket 类和 QUdpSocket 类的基类,包含了这两个类所有的常规功能。您可以通过以下两种方法使用一个套接字( Socket ):

  • 实例化一个 QTcpSocket 或者 QUdpSocket 对象
  • 声明一个自定义套接字描述符,实例化 QAbstractSocket ,然后调用 setSocketDescriptor() 函数包装该自定义套接字描述符。

TCP(传输控制协议)是一种可靠的,面向流,面向连接的传输协议。 UDP(用户数据报协议)是一种不可靠的,面向数据报的无连接协议。 实际上,这意味着TCP更适合于连续数据传输,而当可靠性不重要时,可以使用更轻量的UDP。

QAbstractSocket 的 API 统一了这两种协议之间的大部分差异。 例如,尽管 UDP 是无连接的,但 connectToHost() 为 UDP 套接字建立了虚拟连接,使您可以忽略底层协议,以几乎相同的方式使用 QAbstractSocket 类。 在 QAbstractSocket 类的内部实现中,QAbstractSocket 记录了传递给 connectToHost() 的地址和端口,并且能在调用 read() 和 write() 之类的成员函数时使用这些值。

任何情况下,QAbstractSocket 类都有一个状态state ,该值可以由 state() 成员函数的返回值获得)。 初始状态为未连接QAbstractSocket :: UnconnectedState )状态。 调用 connectToHost() 成员函数连接主机后,套接字会首先进入寻找主机QAbstractSocket :: HostLookupState )状态。 如果找到了主机,则 QAbstractSocket 会进入连接中QAbstractSocket :: ConnectingState )状态,并发送 hostFound() 信号。 建立连接后,它将进入已连接QAbstractSocket :: ConnectedState )状态并发送 connected() 信号。 如果在以上列出任何阶段发生了错误,则会发出 errorOccurred() 信号。 每当状态发生更改时,QAbstractSocket 都会发出 stateChanged() 信号。 为方便起见,当套接字已准备好进行读取和写入数据操作时,isValid() 成员函数的返回值为 true 。但是要注意一下,在进行读写操作之前,套接字的状态必须为已连接QAbstractSocket :: ConnectedState )状态。

您可以通过调用 read() 或 write() 来进行数据读写操作,同时为了方便进行特殊的数据读入操作,您还可以使用 QAbstractSocket 的父类 QIODevice 提供的成员函数 readLine() 和 readAll() 。当我们需要以字节为单位进行数据读写操作时,可以使用 QAbstractSocket 的父类 QIODevice 提供的成员函数 getChar(),putChar() 和 ungetChar() 。 待数据写入套接字后,QAbstractSocket 会发出继承自父类 QIODevice 的信号 bytesWritten() 。请特别注意一下,Qt并不限制写缓冲区的大小。 您可以通过监听 bytesWritten() 信号来监视其大小。

每当有新的数据块到达时,QAbstractSocket 都会发出继承自父类 QIODevice 的信号 readyRead() 。 您可以通过 bytesAvailable() 成员函数的返回值来获得当前读取缓冲区中可读取的字节数。 通常来讲,您可以将 readyRead() 信号与一个槽函数相连接,然后在该槽函数中读取所有可用的数据。 如果您不一次性读取所有数据,则其余数据以后仍可以读取,并且任何新的传入数据都将追加到 QAbstractSocket 的内部读取缓冲区中。您可以通过调用 setReadBufferSize() 成员函数来限制读取缓冲区的大小。

您可以通过调用 disconnectFromHost() 成员函数关闭套接字。 调用 disconnectFromHost() 成员函数后,QAbstractSocket 会进入关闭中QAbstractSocket :: ClosingState )状态。 待所有未处理数据写入套接字后,QAbstractSocket 将关闭套接字,进入未连接QAbstractSocket :: UnconnectedState )状态,并发送 disconnected() 信号。 如果要立即中止连接,并丢弃所有未处理数据,请调用 abort() 成员函数。 如果远程主机关闭了该连接,QAbstractSocket 将发出 errorOccurred(QAbstractSocket :: RemoteHostClosedError) 错误信号,在此期间套接字状态仍为已连接QAbstractSocket :: ConnectedState )状态,此后将发送 disconnected() 信号。

您可以通过调用 peerPort()peerAddress() 成员函数来获取已连接的对等方的端口和地址。 peerName() 成员函数则会返回传递给 connectToHost() 的对等方的主机名。 另外,localPort()localAddress() 成员函数可返回本地套接字的端口和地址。

QAbstractSocket 提供了一组函数,这些函数可以挂起调用线程,直到发出某些信号为止。 这些函数可用于实现阻塞套接字:

Qt官方提供了如下示例:

int numRead = 0, numReadTotal = 0;
char buffer[50];

forever {
	numRead  = socket.read(buffer, 50);

	// do whatever with array

	numReadTotal += numRead;
	if (numRead == 0 && !socket.waitForReadyRead())
		break;
}

waitForReadyRead() 成员函数返回值为 false,则说明连接已关闭或发生了错误。

使用阻塞套接字进行编程与使用非阻塞套接字进行编程完全不同。 阻塞套接字不需要有一个事件循环,这通常可以简化代码。 但是,在GUI应用程序中,阻塞套接字只能在非GUI线程中使用,以避免冻结用户界面。 有关这两种方法的概述,请参见 fortuneclien 和 blockingfortuneclient 示例。

注意: Qt官方并不推荐将阻塞函数与信号一起使用。

QAbstractSocket 可以与 QTextStreamQDataStream 的流运算符(operator<<() 和operator>>())一起使用。 但是,有一个问题需要注意:在尝试使用operator>>() 读取数据之前,必须确保有足够的数据可用。

您也可以在 QNetworkAccessManager 类和 QTcpServer 类的文档中找到一部分相关的信息。

成员类型文档

enum QAbstractSocket::BindFlag | flags QAbstractSocket::BindMode

该枚举描述了一些不同的标志,这些标志可以传递为 bind() 成员函数的参数,指定了不同的主机绑定模式。

常量描述
QAbstractSocket::ShareAddress0x1允许其他服务绑定到相同的地址和端口。 在多个进程通过侦听相同的地址和端口来分担单个服务的负载的情况下(例如,具有多个预分支侦听器的Web服务器可以大大缩短响应时间),该模式十分有效。 但是,由于该模式下允许任何服务对主机进行重新绑定,因此此选项存在着安全隐患。 请注意,您还可以允许您的服务重新绑定现有的共享地址通过将此选项与 QAbstractSocket::ReuseAddressHint 结合使用。 在 Unix 上,这等效于 SO_REUSEADDR 套接字选项。 在 Windows 上,这是默认行为,因此将忽略此选项。
QAbstractSocket::DontShareAddress0x2绑定主机时独占地址和端口,不允许其他服务重新绑定。 将此选项作为 QAbstractSocket :: bind() 参数,可以确保在绑定主机成功后,您当前的服务是唯一侦听指定地址和端口的服务。 即使其他服务通过指定 QAbstractSocket::ReuseAddressHint 模式来绑定服务,这个操作也是不允许的。 该模式相比 QAbstractSocket::ShareAddress 提供了更高的安全性,但是在某些操作系统上,它要求您以管理员权限运行该服务。 在 Unix 和 macOS 上,独占地址和端口是绑定主机的默认行为,因此该选项将被忽略。 在 Windows 上,此选项使用 SO_EXCLUSIVEADDRUSE 套接字选项。
QAbstractSocket::ReuseAddressHint0x4示意 QAbstractSocket 即使地址和端口已被另一个套接字绑定,它也应尝试重新绑定服务。 在 Windows 和 Unix 上,这等效于 SO_REUSEADDR 套接字选项。
QAbstractSocket::DefaultForPlatform0x0使用当前平台的默认模式。 在 Unix 和 macOS 上,这等效于( QAbstractSocket::DontShareAddress + QAbstractSocket::ReuseAddressHint ),在 Windows 上,它等效于 QAbstractSocket::ShareAddress

该枚举最初在Qt5.0版本引入。

BindMode 类型是 typedef QFlags <BindFlag> 生成的用户自定义类型。 它存储着 BindFlag 值的 OR 组合。


enum QAbstractSocket::NetworkLayerProtocol

该枚举描述了Qt中可以使用的网络层协议。

常量描述
QAbstractSocket::IPv4Protocol0IPv4
QAbstractSocket::IPv6Protocol1IPv6
QAbstractSocket::AnyIPProtocol2IPv4 或 IPv6
QAbstractSocket::UnknownNetworkLayerProtocol-1除IPv4和IPv6之外的协议

您也可以在 QHostAddress::protocol() 中找到有关网络层协议的相关知识。


enum QAbstractSocket::PauseMode | flags QAbstractSocket::PauseModes

该枚举描述了套接字在什么情况下该停止传输中的数据。 当前Qt支持的唯一通知是 QSslSocket :: sslErrors() 。

常量描述
QAbstractSocket::PauseNever0x0“永远”不暂停套接字上的数据传输。 该模式是默认设置,符合Qt 4的标准。
QAbstractSocket::PauseOnSslErrors0x1收到 SSL 错误(即 QSslSocket :: sslErrors() )的通知后,暂停套接字上的数据传输。

该枚举最初在Qt5.0版本引入。

PauseModes 类型是 typedef QFlags<PauseMode> 生成的用户自定义类型。它储存着 PauseMode 值的 OR 组合。


enum QAbstractSocket::SocketError

该枚举描述了常见的套接字错误。

常量描述
QAbstractSocket::ConnectionRefusedError0连接被对方拒绝(或连接超时)。
QAbstractSocket::RemoteHostClosedError1远程主机关闭了连接。 请注意,在发送远程主机连接关闭的通知后,客户端套接字(即此套接字)将被关闭。
QAbstractSocket::HostNotFoundError2未能找到主机地址。
QAbstractSocket::SocketAccessError3程序没有权限来进行特定的套接字操作
QAbstractSocket::SocketResourceError4本地系统资源不足(例如本地系统使用了过多的套接字)。
QAbstractSocket::SocketTimeoutError5套接字操作超时。
QAbstractSocket::DatagramTooLargeError6数据报大于操作系统的限制(该限制可以低至8192字节)。
QAbstractSocket::NetworkError7网络发生错误(例如网线断开)。
QAbstractSocket::AddressInUseError8QAbstractSocket::bind() 指定的主机地址已被另一个套接字使用独占模式绑定。
QAbstractSocket::SocketAddressNotAvailableError9QAbstractSocket :: bind() 指定的主机地址不属于主机。
QAbstractSocket::UnsupportedSocketOperationError10本地操作系统不支持请求的套接字操作(例如,缺少IPv6支持)。
QAbstractSocket::ProxyAuthenticationRequiredError12套接字正在使用代理,并且代理需要身份验证。
QAbstractSocket::SslHandshakeFailedError13SSL / TLS 握手失败,因此连接已关闭(仅在 QSslSocket 中使用)。
QAbstractSocket::UnfinishedSocketOperationError11仅由 QAbstractSocketEngine 使用,上一次尝试的操作尚未完成(仍在后台进行)。
QAbstractSocket::ProxyConnectionRefusedError14代理服务器拒绝了连接。
QAbstractSocket::ProxyConnectionClosedError15与代理服务器的连接意外关闭(在建立与对方的最终连接之前)。
QAbstractSocket::ProxyConnectionTimeoutError16与代理服务器的连接超时或代理服务器在身份验证阶段停止响应。
QAbstractSocket::ProxyNotFoundError17找不到使用 setProxy() (或应用程序代理)设置的代理地址。
QAbstractSocket::ProxyProtocolError18与代理服务器通信失败,因为无法理解来自代理服务器的响应,这通常是代理服务协议错误的锅。
QAbstractSocket::OperationError19套接字所处的状态不允许该操作
QAbstractSocket::SslInternalError20使用的 SSL 库出现内部错误。 这可能是由于 SSL 库安装错误或配置错误造成的。
QAbstractSocket::SslInvalidUserDataError21提供了无效的数据(证书,密钥,密码等),其使用导致 SSL 库出现错误。
QAbstractSocket::TemporaryError22发生临时错误(例如,操作将阻塞套接字,而套接字未阻塞)。
QAbstractSocket::UnknownSocketError-1神了,出现了一个未知错误。

您也可以在 QAbstractSocket::error()QAbstractSocket::errorOccurred() 成员函数的详细介绍中找到一部分套接字错误的介绍。


enum QAbstractSocket::SocketOption

该枚举表示可以在套接字上设置的选项。 如果需要设置这些选项,您可以在套接字接收到 connectd() 信号之后,或者在 QTcpServer 接收到新的套接字之后,对它们进行设置。

常量描述
QAbstractSocket::LowDelayOption0尝试优化套接字以降低延迟。 对于 QTcpSocket ,这将设置 TCP_NODELAY 选项并禁用 Nagle 的算法。 将此设置为1启用。
QAbstractSocket::KeepAliveOption1将此设置为1以启用 SO_KEEPALIVE 套接字选项
QAbstractSocket::MulticastTtlOption2将此设置为整数值以设置 IP_MULTICAST_TTL (多播数据报的 TTL )套接字选项。
QAbstractSocket::MulticastLoopbackOption3将此设置为1以启用 IP_MULTICAST_LOOP (多播环回)套接字选项。
QAbstractSocket::TypeOfServiceOption4Windows 不支持此选项。 这映射到IP_TOS套接字选项。 有关其可能的可取值,请参见下表。
QAbstractSocket::SendBufferSizeSocketOption5在操作系统级别设置套接字发送缓冲区的大小(以字节为单位)。 这映射到 SO_SNDBUF 套接字选项。 该选项不会影响 QIODevice 或 QAbstractSocket 缓冲区。 这个枚举值在Qt 5.3中引入。
QAbstractSocket::ReceiveBufferSizeSocketOption6在操作系统级别设置套接字接收缓冲区的大小(以字节为单位)。 这映射到 SO_RCVBUF 套接字选项。 此选项不会影响 QIODevice 或 QAbstractSocket 缓冲区(请参见 setReadBufferSize() )。 这个枚举值已在Qt 5.3中引入。
QAbstractSocket::PathMtuSocketOption7检索IP堆栈当前已知的路径最大传输单位( PMTU )值(如果该值存在)。 一些IP堆栈还允许设置 MTU 进行传输。 这个枚举值在Qt 5.11中引入。

TypeOfServiceOption 可能的可取值(优先级):

描述
224Network control(网络控制)
192Internetwork control(互联网络控制)
160CRITIC/ECP(至关重要)
128Flash override(火速覆盖)
96Flash(火速)
64Immediate(立即)
32Priority(主要)
0Routine(常规)

该枚举最初在Qt4.6版本引入。

您也可以在 QAbstractSocket::setSocketOption()QAbstractSocket::socketOption() 函数介绍中找到相关内容。


enum QAbstractSocket::SocketState

该枚举描述了套接字不同的状态。

常量ValueDescription
QAbstractSocket::UnconnectedState0套接字未连接。
QAbstractSocket::HostLookupState1套接字正在查询主机。
QAbstractSocket::ConnectingState2套接字开始建立连接。
QAbstractSocket::ConnectedState3新的连接已建立。
QAbstractSocket::BoundState4套接字已绑定到一个地址和端口。
QAbstractSocket::ClosingState6套接字即将关闭(数据可能仍在等待写入)。
QAbstractSocket::ListeningState5套接字仅限内部使用。

您也可以在 QAbstractSocket::state() 成员函数介绍中找到相关内容。


enum QAbstractSocket::SocketType

该枚举描述了传输层的协议。

ConstantValueDescription
QAbstractSocket::TcpSocket0TCP
QAbstractSocket::UdpSocket1UDP
QAbstractSocket::SctpSocket2SCTP
QAbstractSocket::UnknownSocketType-1除 TCP, UDP 和 SCTP 外的协议

您也可以在 QAbstractSocket::socketType() 成员函数介绍中找到相关内容。


成员函数文档

QAbstractSocket::QAbstractSocket(QAbstractSocket::SocketType socketType, QObject *parent)

创建一个新抽象套接字 socketType 。 函数中父对象的参数传递给 QObject 的构造函数。

这就是它的构造函数嘛,没啥好说的。另外由于 QAbstractSocket 类继承自 QObject 类,应注意在 QAbstractSocket 类构造函数中调用一下父类 QObject 类的构造函数。

另外您也可以在 socketType() 成员函数文档,以及 QTcpSocketQUdpSocket 类文档找到相关信息。


[SIGNAL] void QAbstractSocket::connected()

connectToHost() 调用并成功建立一个连接后,QAbstractSocket 类将发送 connectd() 信号。

注意: 在某些操作系统上,connected() 信号可能直接从 connectToHost() 调用发出,以连接到本地主机。

另外您也可以在 connectToHost()disconnected() 成员函数文档中找到相关信息。


[SIGNAL] void QAbstractSocket::disconnected()

套接字断开后会发送该信号。

警告: 如果您想在与这个信号相连接的槽函数中删除信号的发送者( sender() ),请使用 deleteLater() 函数。

另外您也可以在 connectToHost()disconnectFromHost()abort() 函数介绍中找到相关信息。


[SIGNAL] void QAbstractSocket::errorOccurred(QAbstractSocket::SocketError socketError)

当套接字遇到错误时会发送该信号。socketError 参数描述了该错误类型。

发出此信号后,套接字可能并未准备好进行重新连接。 在这种情况下,我们应尝试从事件循环中进行重新连接。 例如我们可以调用一个QTimer::singleShot(),并将0作为时间间隔。

请注意,QAbstractSocket :: SocketError 并不是Qt预注册好的元类型。因此如果您要在队列连接( queued connections )模式的信号与槽的连接中传递该类型的参数,您必须使用 Q_DECLARE_METATYPE() 和 qRegisterMetaType() 注册它为元类型。

该函数在Qt5.15版本引入。

另外您也可以在 error() 和 errorString() 函数介绍以及 Creating Custom Qt Types 文档中找到相关信息。


[SIGNAL] void QAbstractSocket::hostFound()

在 QAbstractSocket 调用 connectToHost() 函数并成功找到主机后,它将发送该消息。

注意: 从Qt 4.6.3开始,由于可能已缓存DNS结果,因此 QAbstractSocket 可能直接在调用 connectToHost() 时发送 hostFound() 信号。

另外您也可以在 connectd() 函数介绍中找到相关信息。


[SIGNAL] void QAbstractSocket::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)

套接字连接的代理服务期需要身份验证时会发送该消息。您可以用所需的详细信息填充 authenticator 对象,以便代理服务期进行身份验证并继续连接。

注意: 如果信号返回时未使用新信息填充 authenticator ,则连接将失败,因此您不能使用队列连接模式( QueuedConnection )连接到该信号。

该函数首次在Qt4.3版本引入。

另外您也可以在 QAuthenticatorQNetworkProxy 文档中找到相关信息。


[SIGNAL] void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)

QAbstractSocket 状态发生改变后会发送该信号。socketState 参数记录了新的状态。

请注意,QAbstractSocket :: SocketState 并不是Qt预注册好的元类型。因此如果您要在队列连接( queued connections )模式的信号与槽的连接中传递该类型的参数,您必须使用 Q_DECLARE_METATYPE() 和 qRegisterMetaType() 注册它为元类型。

另外您也可以在 state() 成员函数介绍和 Create Custom Qt Types 文档中找到相关信息。


[virtual] QAbstractSocket::~QAbstractSocket()

析构函数,销毁套接字。


void QAbstractSocket::abort()

中止当前连接并重置套接字。 与 disconnectFromHost() 不同,此函数会立即关闭套接字,并丢弃写缓冲区中的所有未处理数据。

另外您也可以在 disconnectFromHost()close() 函数介绍中找到相关信息。


[override virtual] bool QAbstractSocket::atEnd() const

该函数重写了父类 QIODevice 的类成员函数 QIODevice::atEnd() const

如果当前没有更多数据可读取,则返回 true ,否则返回 false 。

在循环中从套接字读取数据时,最常使用此功能。 例如:

// This slot is connected to QAbstractSocket::readyRead()
void SocketClass::readyReadSlot()
{
	while (!socket.atEnd()) {
		QByteArray data = socket.read(100);
		....
	}
}

另外您也可以在 bytesAvailable() 和 readyRead() 函数介绍中找到相关信息。


bool QAbstractSocket::bind(const QHostAddress &address, quint16] port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)

使用 mode 指定的 QAbstractSocket::BindMode 模式绑定到 addressport 指定的地址和端口上。

对于 UDP 套接字来说,在使用 bind() 绑定主机后,只要 UDP 数据报到了达指定的地址和端口,就会发出 QUdpSocket :: readyRead() 的信号。 因此,此功能对于编写UDP服务器很有用。

对于 TCP 套接字来说,此功能可用于指定将哪个接口用于传出连接,这在多个网络接口的情况下很有用。

默认情况下, QAbstractSocket 会使用 DefaultForPlatform BindMode 模式绑定套接字。 如果未指定端口 port ,则 QAbstractSocket 会选择一个随机端口。

成功后,函数返回 true ,套接字进入 已绑定BoundState )状态; 否则返回 false 。

该函数最初在Qt5.0版本引入。


bool QAbstractSocket::bind(quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)

重载 bind() 函数。

该函数会使用 mode 指定的 QAbstractSocket::BindMode 模式绑定到主机上的任何地址( QHostAddress:Any ) 和 port 指定的端口上。

默认情况下, QAbstractSocket 会使用 DefaultForPlatform BindMode 模式绑定套接字。 如果未指定端口 port ,则 QAbstractSocket 会选择一个随机端口。

该函数最初在Qt5.0版本引入。


[override virtual] qint64 QAbstractSocket::bytesAvailable() const

该函数重写了父类 QIODevice 的类成员函数 QIODevice::bytesAvailable() const

返回等待读取的传入字节数。

另外您也可以在 bytesToWrite() 和 read() 函数介绍中找到相关信息。


[override virtual] qint64 QAbstractSocket::bytesToWrite() const

该函数重写了父类 QIODevice 的类成员函数 QIODevice::bytesToWrite() const

返回等待写入的字节数。 当控制权返回事件循环或调用 flush() 时,这些字节将会被写入。

另外您也可以在 bytesAvailable()flush() 函数介绍中找到相关信息。


[override virtual] bool QAbstractSocket::canReadLine() const

该函数重写了父类 QIODevice 的类成员函数 QIODevice::canReadLine() const

如果能从该套接字中读取一行数据时返回 true,否则返回 false 。

另外您也可以在 readLine() 函数介绍中找到相关信息。


[override virtual] void QAbstractSocket::close()

该函数重写了父类 QIODevice 的类成员函数 QIODevice::close()

关闭套接字的 I/O 设备并调用 disconnectFromHost() 来关闭套接字的连接。

您可以阅读 QIODevice::close() 的介绍来查阅关闭 I/O 设备时发生的操作。

另外您也可以在 abort() 函数介绍中找到相关信息。


[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, QIODevice::OpenMode openMode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)

尝试连接到远程主机 hostname 的给定端口 portprotocol 参数可用于指定要使用的网络协议(例如IPv4或IPv6)。

使用 openMode 给定的模式打开套接字并进入 寻找主机HostLookupState )状态,然后 QAbstractSocket 开始执行主机名查找操作。 成功查找到主机名后, QAbstractSocket 会发出 hostFound() 信号,并进入连接中ConnectingState )状态。 接着 QAbstractSocket 会尝试连接到上一部查找主机后返回的一个或多个地址。 最终建立连接后,QAbstractSocket 会进入已连接ConnectedState )并发送 connectd() 信号。

在以上的任意一阶段中遇到错误,套接字都会发送 errorOccurred() 信号。

hostName 参数可以是一个字符串形式的IP地址(例如"49.195.83.32"),也可以是一个主机名(例如"example.com")。QAbstractSocket 仅在需要时才会进行查找。 port 端口参数按本机字节顺序。

另外您也可以在 state()peerName()peerAddress()peerPort()waitForConnected() 函数介绍中找到相关信息。


[virtual] void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, QIODevice::OpenMode openMode = ReadWrite)

重载 connectToHost() 函数。

尝试连接到远程主机 hostname 的给定端口 port


[virtual] void QAbstractSocket::disconnectFromHost()

尝试关闭套接字。如果还有未处理的数据等待写入,QAbstractSocket 会进入正在关闭ClosingState )状态并等待所有数据被写入后再关闭套接字。最终 QAbstractSocket 会进入未连接UnconnectedState )状态并发送 disconnected() 信号。

另外您也可以在 connectToHost() 函数介绍中找到相关信息。


QAbstractSocket::SocketError QAbstractSocket::error() const

返回最后一个错误的类型。

另外您也可以在 state() 和 errorString() 函数介绍中找到相关信息。


bool QAbstractSocket::flush()

该函数尽可能多的在不阻塞套接字的前提下将数据从内部写入缓冲区写入基础网络套接字。 如果写入了任何数据,则此函数返回 true , 否则返回 false 。

可成功写入的字节数取决于操作系统。请仅在需要 QAbstractSocket 立即开始发送缓冲的数据的情况下调用此函数。 在大多数情况下,您不需要调用此函数,因为一旦控制权返回事件循环,QAbstractSocket 将自动开始发送数据。 在没有事件循环的情况下,请改为调用 waitForBytesWritten()

另外您也可以在 write() 和 waitForBytesWritten() 函数介绍中找到相关信息。


[override virtual] bool QAbstractSocket::isSequential() const

该函数重写了父类 QIODevice 的类成员函数 QIODevice::isSequential()


bool QAbstractSocket::isValid() const

如果套接字有效并且可以使用,则返回 true ,否则返回 false 。

注意: 在进行读写操作之前,套接字必须处于已连接ConnectedState )状态。

另外您也可以在 state() 函数介绍中找到相关信息。


QHostAddress QAbstractSocket::localAddress() const

如果本地套接字则可用返回主机地址,否则返回 QHostAddress::Null

返回的主机地址通常是主机的IP地址。但是当套接字连接到本地主机时,返回的主机地址为 QHostAddress::LocalAddress

另外您也可以在 localPort()peerAddress()setLocalAddress() 函数介绍中找到相关信息。


quint16 QAbstractSocket::localPort() const

如果本地套接字可用则按照本地字节顺序返回主机端口,否则返回0。

另外您也可以在 localAddress()peerPort()setLocalPort() 函数介绍中找到相关信息。


QAbstractSocket::PauseModes QAbstractSocket::pauseMode() const

返回该套接字的数据传输暂停模式。

该函数最初在Qt5.0版本引入。

另外您也可以在 setPauseMode()resume() 函数介绍中找到相关信息。


QHostAddress QAbstractSocket::peerAddress() const

如果套接字处于已连接ConnectedState )状态则返回对等端的地址,否则返回 QHostAddress::Null

另外您也可以在 peerName()peerPort()localAddress()setPeerAddress() 函数介绍中找到相关信息。


QString QAbstractSocket::peerName() const

返回在 connectToHost() 函数中指定的主机名。如果 connectToHost() 函数未被调用过则返回一个空的 QString 。

另外您也可以在 peerAddress()peerPort()setPeerName() 函数介绍中找到相关信息。


quint16 QAbstractSocket::peerPort() const

如果套接字处于已连接ConnectedState )状态则返回对等端的端口,否则返回0。

另外您也可以在 peerAddress()localPort()setPeerPort() 函数介绍中找到相关信息。


QString QAbstractSocket::protocolTag() const

返回此套接字的协议标签。 如果设置了协议标签,则在 QAbstractSocket 内部创建协议标签时将其传递给QNetworkProxyQuery,以指示要使用的协议标签。

该函数最初在Qt5.13版本引入。

另外您也可以在 setProtocolTag() 函数介绍和 QNetworkProxyQuery 文档中找到相关信息。


QNetworkProxy QAbstractSocket::proxy() const

返回该套接字的网络代理。默认情况下套接字会使用 QNetworkProxy::DefaultProxy ,套接字会查询应用程序的默认网络代理设置。

该函数最早在Qt4.1版本引入。

另外您也可以在 setProxy() 函数介绍以及 QNetworkProxyQNetworkProxyFactory 文档中找到相关信息。


qint64 QAbstractSocket::readBufferSize() const

返回内部读取缓冲区的大小。 这限制了客户端在调用 read() 或 readAll() 之前可以接收的数据量。

读取缓冲区大小为0(默认值)意味着缓冲区没有大小限制,从而确保没有数据丢失。

另外您也可以在 setReadBufferSize() 和 read() 函数介绍中找到相关信息。


[override virtual protected] qint64 QAbstractSocket::readData(char *data, qint64 maxSize)

该函数重写了父类 QIODevice 的类成员函数 QIODevice::readData()


[override virtual protected] qint64 QAbstractSocket::readLineData(char *data, qint64 maxlen)

该函数重写了父类 QIODevice 的类成员函数 QIODevice::readLineData()


[virtual] void QAbstractSocket::resume()

继续套接字数据传输。 仅当将套接字设置为收到暂停的消息后暂停数据传输,并接收到暂停的消息后暂停了数据传输,才能使用此方法。 当前支持的唯一通知是 QSslSocket :: sslErrors() 。 如果套接字未暂停,则调用此方法将导致 未定义的行为undefined behavior )。

该函数最初在Qt5.0版本引入。

另外您也可以在 pauseMode()setPauseMode() 函数介绍中找到相关信息。


[protected] void QAbstractSocket::setLocalAddress(const QHostAddress &address)

将套接字连接中本地的地址设置为 address

套接字连接建立后,您可以在 QAbstractSocket 的子类中调用此函数以更改 localAddress() 函数的返回值。 代理连接通常将此功能用于虚拟连接设置。

请注意,此函数在连接之前不会绑定套接字的本地地址(例如 QAbstractSocket :: bind() )。

该函数最初在Qt4.1版本引入。

另外您也可以在 localAddress()setLocalPort()setPeerAddress() 函数介绍中找到相关知识。


[protected] void QAbstractSocket::setLocalPort(quint16 port)

将套接字连接中本地的端口设置为 port

套接字连接建立后,您可以在 QAbstractSocket 的子类中调用此函数以更改 localPort() 函数的返回值。 代理连接通常将此功能用于虚拟连接设置。

请注意,此函数在连接之前不会绑定套接字的本地端口(例如 QAbstractSocket :: bind() )。

该函数最初在Qt4.1版本引入。

另外您也可以在 localPort()localAddress()setLocalPort()setPeerAddress()


void QAbstractSocket::setPauseMode(QAbstractSocket::PauseModes pauseMode)

设置套接字是否在收到通知后暂停数据传输。 pauseMouse 参数指定套接字暂停的条件。目前唯一支持的暂停套接字数据传输的信号是 QSslSocket::sslErrors() 。如果将套接字暂停模式设置为 PauseOnSslErrors ,在接收到 QSslSocket::sslErrors() 信号后套接字上的数据传输将被暂停,并且需要通过调用 resume() 再次显式启用。默认情况下 QAbstractSocket 暂停模式为 PauseNever 。 若要修改暂停模式,您必须在连接服务器前调用此函数,否则对此函数的调用将被视为未定义行为。

该函数最初在Qt5.0版本引入。

另外您也可以在 pauseMode()resume() 函数介绍中找到相关信息。


[protected] void QAbstractSocket::setPeerAddress(const QHostAddress &address)

设将套接字连接中远程的地址设置为 address

您可以在 QAbstractSocket 的一个子类中去改变 peerAddress() 函数的返回值。 代理连接通常将此功能用于虚拟连接设置。

该函数最早在Qt4.1版本引入。

另外您也可以在 peerAddress()setPeerPort()setLocalAddress() 函数介绍中找到相关信息。


[protected] void QAbstractSocket::setPeerName(const QString &name)

设将套接字连接中远程的主机名设置为 name

套接字连接建立后,您可以在 QAbstractSocket 的子类中调用此函数以更改 peerName() 函数的返回值。 代理连接通常将此功能用于虚拟连接设置。

该函数最早在Qt4.1版本引入。

另外您也可以在 peerName()函数介绍中找到相关信息。


[protected] void QAbstractSocket::setPeerPort(quint16 port)

设将套接字连接中远程的端口设置为 port

套接字连接建立后,您可以在 QAbstractSocket 的子类中调用此函数以更改 peerPort() 函数的返回值。 代理连接通常将此功能用于虚拟连接设置。

该函数最早在Qt4.1版本引入。

另外您也可以在 peerPort() 函数介绍中找到相关信息。


void QAbstractSocket::setProtocolTag(const QString &tag)

将此套接字的协议标签设置为 tag

该函数最早在Qt5.13版本引入。

另外您也可以在 protocolTag() 函数介绍中找到相关信息。


void QAbstractSocket::setProxy(const QNetworkProxy &networkProxy )

将此套接字的显式网络代理设置为 networkProxy

您可以通过指定 networkProxyQNetworkProxy::NoProxy 以禁止套接字使用代理网络:

socket->setProxy(QNetworkProxy::NoProxy);

套接字默认使用的代理为 QNetworkProxy::DefaultProxy 即套接字会使用应用程序的代理设置,将代理设置为 QNetworkProxy::setApplicationProxy 也可以达到同样的效果。如果您使用 QNetworkProxyFactory :: setApplicationProxyFactory 设置了 QNetworkProxy 插件工厂,它将使用 QNetworkProxyQuery :: TcpSocket 类型查询该插件工厂。

该函数最早在Qt4.1版本引入。

另外您也可以在 proxy() 函数介绍以及 QNetworkProxy 和 QNetworkProxyFactory::queryProxy() 文档中找到相关信息。


[virtual] void QAbstractSocket::setReadBufferSize(qint64 size)

设置 QAbstractSocket 内部读入缓冲区的大小(字节为单位)。

如果将该缓冲区的大小设置为一个确定的值,QAbstractSocket 内部读入缓冲区内的值大小超过该值后,便不会再缓冲数据。与此相反,缓冲区大小为0意味着读缓冲区不受限制,所有传入数据都将被缓冲,同时这也是默认值。

该功能在特定的情况下(例如,在实时流应用程序中)读取数据,或者要保护套接字避免接收过多的数据(可能最终导致应用程序用尽内存)很有用。

只有QTcpSocket使用 QAbstractSocket 的内部缓冲区。 QUdpSocket 根本不使用任何缓冲,而是依赖于操作系统提供的隐式缓冲。 因此,在 QUdpSocket 上调用此函数无效。

另外您也可以在 readBufferSize() 和 read() 函数介绍中找到相关信息。


[virtual] bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = ConnectedState, QIODevice::OpenMode openMode = ReadWrite)

使用本机套接字描述符 socketDescriptor 初始化 QAbstractSocket 。 如果 socketDescriptor 为有效的套接字描述符,则返回 true ,否则返回 false 。 套接字以 openMode 指定的模式打开,并进入由 socketState 指定的套接字状态。 读取和写入缓冲区将会丢弃所有未决数据并清空。

注意: 无法使用相同的本机套接字描述符初始化两个抽象套接字。

另外您也可以在 socketDescriptor() 函数介绍中找到相关信息。


[proteched] void QAbstractSocket::setSocketError(QAbstractSocket::SocketError socketError)

将套接字最后一个出现的错误的类型设置为 socketError

另外您也可以在 setSocketState() 和 setErrorString() 函数中找到相关信息。


[virtual] void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)

option 指定的套接字选项设置为 value 指定的值。

注意: 当应用程序在 Windows 下运行时, QAbstractSocket::KeepAliveOption 选项的值必须在套接字连接之前指定。

该函数最初在Qt4.6版本引入。

另外您也可以在 socketOption() 函数介绍中找到相关信息。


[protected] void QAbstractSocket::setSocketState(QAbstractSocket::SocketState state)

将套接字的状态设置为 state

另外您也可以在state() 函数介绍中找到相关信息。


[virtual] qintptr QAbstractSocket::socketDescriptor() const

当 QAbstractSocket 类对象的本地套接字描述符可用时,则返回该描述符,否则返回-1。

如果套接字使用了网络代理,则返回的描述符可能无法与本机套接字一起使用。

当 QAbstractSocket 类处于未连接UnconnectedState)状态时,该描述符是不可用的。

另外您也可以在 setSocketDescriptor() 函数介绍中找到相关信息。


[virtual] QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption) option)

返回 option 指定的套接字选项的值。

该函数最早在Qt4.6版本引入。

另外您也可以在 setSocketDescriptor() 函数介绍中找到相关信息。


QAbstractSocket::SocketType QAbstractSocket::socketType() const

返回套接字类型( TCP,UDP,或者其他)。

另外您也可以在 QTcpSocketQUdpSocket 文档中找到相关信息。


QAbstractSocket::SocketState QAbstractSocket::state() const

返回套接字的当前状态。

另外您也可以在 error() 函数介绍中找到相关信息。


[override virtual] bool QAbstractSocket::waitForBytesWritten(int msecs = 30000)

该函数重写了父类 QIODevice 的类成员函数 QIODevice::waitForBytesWritten(int msecs)

该函数将阻塞套接字通信直到至少一个字节被写入到套接字并发送 bytesWritten() 信号为止。 函数将会在 msecs 指定的时间后超时,默认的超时时间设置为30000毫秒。

bytesWritten() 信号发出后该函数返回值为 true,偶则返回 false (如果有一个错误发生或者该操作超时)。

注意: 在 Windows 上,此功能可能会随机性地失败。 如果您的软件将在 Windows 上运行,请考虑使用事件循环和 bytesWritten() 信号。

另外您也可以在 waitForReadyRead() 函数介绍中找到相关信息。


[virtual] bool QAbstractSocket::waitForConnected(int msecs = 30000)

msecs 指定的时间内等待套接字连接到主机。如果连接成功建立,则返回 true ,否则返回 false 。如果该函数返回 false ,您可以调用 error() 函数来确定连接中出现的错误的类型。

这里Qt官方给了一个1秒内等待套接字建立到主机的连接的示例:

socket->connectToHost("imap", 143);
if (socket->waitForConnected(1000))
	qDebug("Connected!");

如果将 msecs 设置为-1,这个函数将不会超时。

注意: 由于套接字完成主机的查询需要一定时间,这个函数超时的时间可能会比 msecs 设定的时间要轻微的长一些。

注意: 多次调用这个函数并不会累积超时时间。如果函数超时,套接字的连接进程就会被中断。

注意: 在 Windows 上,此功能可能会随机性地失败。 如果您的软件将在 Windows 上运行,请考虑使用事件循环和 connected() 信号。

另外您也可以在 connectToHost()connected() 函数中找到相关信息。


[virtual] bool QAbstractSocket::waitForDisconnected(int msecs = 30000)

msecs 指定的时间内等待套接字从主机断开连接。 如果连接成功断开,则返回 true ,否则返回 false (操作超时,出现错误,或者已经断开连接)。 如果该函数返回 false ,您可以调用 error() 函数来确定断开连接时出现的错误的类型。

这里Qt官方给了一个1秒内等待套接字从主机断开连接的示例:

socket->disconnectFromHost();
if (socket->state() == QAbstractSocket::UnconnectedState
	|| socket->waitForDisconnected(1000)) {
		qDebug("Disconnected!");
 }

如果 msecs 设为-1,该函数将不会超时。

注意: 在 Windows 上,此功能可能会随机性地失败。 如果您的软件将在 Windows 上运行,请考虑使用事件循环和 disconnected() 信号。

另外您也可以在 disconnectFromHost() 和 close() 函数介绍中找到相关信息。


[override virtual] bool QAbstractSocket::waitForReadyRead(int msecs = 30000)

该函数重写了父类 QIODevice 的类成员函数 QIODevice::waitForReadyRead(int msecs)

该函数将阻塞套接字通信直到有新的字节可以读取并发送 readyRead() 信号为止。 函数将会在 msecs 指定的时间后超时,默认的超时时间设置为30000毫秒。

readyRead() 信号发出后该函数返回值为 true,偶则返回 false (如果有一个错误发生或者该操作超时)。

注意: 在 Windows 上,此功能可能会随机性地失败。 如果您的软件将在 Windows 上运行,请考虑使用事件循环和 readyRead() 信号。

另外您也可以在 waitForBytesWritten()() 函数介绍中找到相关信息。


[overrude virtual protected] qint64 QAbstractSocket::writeData(const char *data, qint64 size)

该函数重写了父类 QIODevice 的类成员函数 QIODevice::writeData(const char data, qint64 size)。

Reserved by yangle until 2020-08-31.

最佳实践指南

这些文档为使用 Qt 解决特定的技术问题提供指南和最佳实践,可用以指导开发者,如何尽可能使用 Qt 技术创建具有卓越的可用性和软件设计的应用程序。

页面描述
可访问性如何让残障人士能够访问您的应用程序。
Qt Quick 应用程序的可访问性如何让残障人士能够访问您的应用程序。
QML 和 Qt Quick 最佳实践列举了使用 QML 和 Qt Quick 时的最佳实践。
有关 GUI 设计的书籍有关 GUI 设计的一些推荐书籍。
从 Unix 信号处理程序调用 Qt 函数这做不到。但不用灰心,我们依然有办法变通……
坐标系统关于绘制系统使用到的坐标系统的一些信息。
创建自定义 Qt 类型如何使用 Qt 创建和注册新类型。(译者注:即被元对象系统支持的动态类型
创建共享库如何创建共享库。
为 Qt Designer 创建和使用组件如何创建和使用自定义 Widget 插件。
桌面集成与用户桌面环境进行集成。
异常安全Qt 中的异常安全指南。
如何创建 Qt 插件如何创建用于扩展 Qt 应用和功能的插件的指南。
实现原子操作关于如何在新的 CPU 架构上实现原子操作。
QtTest教程使用 Qt Test 进行测试的简短介绍。
还原窗口几何形状如何保存/还原窗口的几何形状。
富文本处理关于 Qt 的富文本处理、编辑和显示的概述。
可伸缩性如何在不同的屏幕设置和界面约定的设备中开发可以良好适配的应用程序。
会话管理如何使用 Qt 管理会话。
设置应用程序图标如何设置应用程序的图标。
标准加速键推荐的加速键(译者注:即快捷键)。
定时器如何在应用程序中使用 Qt 定时器。
使用 Qt D-Bus 适配器如何在 Qt 中创建和使用 DBus 适配器。

容器

引言

Qt 提供了一系列基于模板的通用容器类,可以用于存储指定类型的元素。例如,如果你需要一个可动态调整大小的 QString 数组,那么你可以使用 QVector<QString>。

这些类的设计目标是比 STL 容器更轻量,更安全,更易用。如果你不熟悉 STL,或想更有“ Qt 范”,使用这些类代替 STL 会是更好的选择。

这些类都是隐式共享可重入的,并且针对几个方面做了优化,一是速度,二是较低的内存占用,三是尽可能少的内联代码,减少生成程序的体积。另外,在所有线程都以只读的方式访问容器时,这些类是线程安全的。

要遍历容器中的元素,你可以使用两种风格迭代器:Java 风格迭代器STL 风格迭代器。Java 风格迭代器有更好的易用性和更高级的函数,而 STL 风格迭代器则在效率上会略有优势,并且可以用于 Qt 和 STL 提供的泛型算法中。

Qt 还提供了 foreach 关键字,可以方便地遍历容器。

:从 Qt 5.14 开始,绝大部分容器类已经支持范围构造函数,但需要注意的是 QMultiMap 是一个例外。我们推荐使用该特性代替各种 from/to 方法。例如:

译者注:这里的 from/to 方法指的是 Qt 容器类提供的以 from/to 开头的转换方法,如QVector::toList

QVector<int> vector{1, 2, 3, 4, 4, 5};
QSet<int> set(vector.begin(), vector.end());
/*
    将会生成一个 QSet,包含元素 1, 2, 4, 5。
*/

容器类

Qt 提供了以下几种顺序容器:QListQLinkedListQVectorQStackQQueue。对于大多数的应用,QList 是最适用的。虽然其基于数组实现,但支持在头部和尾部快速插入。如果确实需要一个基于链表的列表,你可以使用 QLinkedList;如果要求元素以连续内存的形式保存,那么可以使用 QVectorQStack QQueue提供了 LIFO 和 FIFO 语义的支持。

Qt也提供了一系列关联容器:QMapQMultiMapQHashQMultiHashQSet。"Multi" 容器可以方便地支持键值一对多的情形。“Hash” 容器提供了快速查找的能力,这是通过使用哈希函数代替对有序集合进行二分查找实现的。

较为特殊的是 QCacheQContiguousCache,这两个类提供了在有限的缓存中快速查找元素的能力。

综述
QList这是目前使用最普遍的容器类,其保存了一个元素类型为T的列表,支持通过索引访问。QList 内部通过数组实现,以确保基于索引的访问足够快。
元素可以通过 QList::append()QList::prepend() 插入到首尾,也可以通过 QList::insert() 插入到列表中间,和其他容器类不同的是,QList 为生成尽可能少的代码做了高度优化。QStringList 继承于 QList<QString>。
QLinkedList)这个类和 QList 很像,不同的是这个类使用迭代器进行而不是整形索引对元素进行访问。和 QList 相比,其在中间插入大型列表时其性能更优,而且其具有更好的迭代器语义。(在 QLinkedList 中,指向一个元素的迭代器只要该元素存在,则会一直保持有效,而在 QList 的迭代器则可能会在任意的元素插入或删除后失效。)
QVector这个类以数组的形式保存给定类型的元素,在内存中元素彼此相邻。在一个 vector 的头部或中部插入可能会相当慢,因为这可能会导致大量元素需要在内存中移动一个位置。
QVarLengthArray<T, Prealloc>这个类提供了一个底层的变长数组,在速度极其重要的情况下可以用来代替 QVector
QStack这个类继承于 QVector,用于为”后进,先出”(LIFO )提供便捷的语义支持。其为 QVector 添加了以下方法:QVector::push()pop()top()
QQueue这个类继承于 QVector,用于为”先进,先出”(FIFO )提供便捷的语义支持。其为 QVector 添加了以下方法:QList::enqueue()dequeue()head()
QSet这个类提供了一个单值数学集合,支持快速查找
QMap<Key, T>这个类提供了一个将类型为Key的键映射到类型为T的值的字典(关联数组)。通常情况下键值是一一对应的。QMap 根据Key进行排序,如果排序无关紧要,使用 QHash 代替速度会更快
QMultiMap<Key, T>这个类继承于 QMap,其为诸如键值一对多的多值映射提供了一个友好的接口
QHash<Key, T>这个类几乎与 QMap 有完全一致的 API ,但查找效率会有明显的提高。QHash 的数据是无序的。
QMultiHash这个类继承于 QMap,其为多值映射提供了一个友好的接口

容器可以嵌套。例如在键为 QString,值为 QList 时,完全可以使用 QMap<QString, QList>。

容器类的定义位于和容器同名的独立头文件中(例如,<QLinkedList>)。为了方便,在 <QtContainerFwd> 中对所有容器类进行了前置声明。

保存在各个容器中的值类型可以是任意可复制数据类型。为了满足这一要求,该类型必须提供一个复制构造函数和一个赋值运算符。某些操作可能还要求类型支持默认构造函数。对于大多数你想要在容器中保存的类型都满足这些要求,包括基本类型,如 intdouble,指针类型,以及 Qt 数据类型,如 QStringQDate QTime,但并不包括 QObject 及其子类(QWidgetQDialogQTimer 等)。如果你尝试实例化一个 QList<QWidget>,编译器将会抱怨道 QWidget 的复制构造函数和赋值运算符被禁用了。如果需要在容器中保存这些类型的元素,可以保存其指针,如 QList<QWidget *>。

下面是一个满足可赋值数据类型要求的自定义数据类型的例子:

class Employee
{
public:
    Employee() {}
    Employee(const Employee &other);

    Employee &operator=(const Employee &other);

private:
    QString myName;
    QDate myDateOfBirth;
};

如果我们没有提供一个复制构造函数或一个赋值运算符,C++ 将会提供一个表现为逐个复制成员的默认实现。在上面的例子中,默认行为就足够了。同样的,如果没有提供默认构造函数,C++ 会提供一个默认构造函数,对成员进行默认构造。尽管没有提供任何的构造函数或赋值运算符,下面的数据类型可以被保存于容器中。

struct Movie
{
    int id;
    QString title;
    QDate releaseDate;
};

一些容器对它们所能保存的数据类型有额外的要求。举个例子,QMap<Key, T> 的键类型 Key 必须提供 operator<() 方法。这些特殊要求在类的详细描述中有说明。在某些情况下,特定函数会有特定的要求,这在函数的描述中有说明。如果条件不满足,编译器将总是会报错。

Qt容器提供了 operator<<()operator>>(),因此这些类可以很方便地通过 QDataStream 进行读写。这意味着存储在容器中的元素类型也必须支持 operator<<()operator>>()。支持这一点是很简单的;以下是我们使上面的 Movie 结构体支持这一点所做的改动:

QDataStream &operator<<(QDataStream &out, const Movie &movie)
{
    out << (quint32)movie.id << movie.title
        << movie.releaseDate;
    return out;
}

QDataStream &operator>>(QDataStream &in, Movie &movie)
{
    quint32 id;
    QDate date;

    in >> id >> movie.title >> date;
    movie.id = (int)id;
    movie.releaseDate = date;
    return in;
}

某些容器类的文档中会提到默认值;举个例子,QVector 会自动使用默认值初始化其元素;QMap::value() 在指定键不存在时会返回一个默认值。对于大部分的值类型,这就是简单地代表通过默认构造函数创建的值(例如对于 QString 即空字符串)。但是对于基本类型,如 intdouble 和指针类型,C++ 语言并没有规定任何的初始化方式,因此在这些情况下,Qt 容器将会自动将其初始化为0。

迭代器类

迭代器提供了一个统一的方式去访问容器中的元素。Qt 容器类提供了两种风格迭代器:Java 风格迭代器和 STL 风格迭代器。两种迭代器均会在容器中的数据被修改或因调用非 const 成员函数导致数据从隐式共享中分离后失效。

Java 风格迭代器

Java 风格迭代器在 Qt4 中引入,作为标准使用在Qt应用中。和 STL 风格迭代器相比,其易用性更高,代价是性能略低。该风格迭代器 API 以 Java 迭代器类为原型设计。

对于每一个容器类,同时提供了两种数据类型的 Java 风格迭代器:一种支持只读访问,另一种支持读写访问。

容器只读迭代器读写迭代器
QList, QQueueQListIteratorQMutableListIterator
QLinkedListQLinkedListIteratorQMutableLinkedListIterator
QVector, QStackQVectorIteratorQMutableVectorIterator
QSetQSetIteratorQMutableSetIterator
QMap<Key, T>, QMultiMap<Key, T>QMapIterator<Key, T>QMutableMapIterator<Key, T>
QHash<Key, T>, QMultiHash<Key, T>QHashIterator<Key, T>QMutableHashIterator<Key, T>

在接下来的讨论中,我们将重点关注 QListQMapQLinkedListQVectorQSet 的迭代器类型和 QList 有完全一样的接口,类似的,QHashQMap 的迭代器类型的接口也是相同的。

和 STL 风格迭代器(下一节介绍)不同,Java 风格迭代器指向的是元素间隙而不是元素本身。因此,Java 风格迭代器可以指向容器最前(在第一个元素之前),也可以指向容器最后(在最后一个元素之后),还可以指向两个元素之间。下图用红色箭头展示了一个四个元素的列表容器合法的迭代器位置。

Java style iterator

这是一个通过循环迭代有序遍历 QList<QString> 中的所有元素并打印到终端的常用写法:

QList<QString> list;
list << "A" << "B" << "C" << "D";

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

它的工作原理如下:需要被迭代的 QList 对象作为参数传递给 QListIterator 的构造函数。此时迭代器位于列表中第一个元素的前面(位于元素“A“之前)。接着我们调用 hasNext() 检查迭代器之后是否有元素,如果有,我们调用 next() 跳过这个元素。next() 方法会返回其跳过的元素。对于 QList<QString> 类型,元素的类型为 QString

下列代码展示了如何反向迭代一个 QList

QListIterator<QString> i(list);
i.toBack();
while (i.hasPrevious())
    qDebug() << i.previous();

这段代码的逻辑和前向迭代是对称的除了在开始我们调用了 toBack() 将迭代器移动到列表中最后一个元素之后。

下图说明了在迭代器上调用 next()previous() 产生的效果:

list iterator

下表总结了QListIterator的 API:

函数行为
toFront()移动迭代器到列表最前(第一个元素之前)
toBack()移动迭代器到列表最后(最后一个元素之后)
hasNext()如果迭代器不在列表最后则返回 true
next()返回下一个元素并将迭代器前移一位
peekNext()不移动迭代器,仅返回迭代器下一个元素
hasPrevious()如果迭代器不在列表最前则返回 true
previous()返回前一个元素并将迭代器后移一位
peekPrevious()不移动迭代器,仅返回迭代器前一个元素

QListIterator 没有提供任何在迭代列表时插入或删除元素的方法。要实现这一点,你必须使用 QMutableListIterator。这是一个使用 QMutableListIteratorQList 中移除所有奇数的例子:

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

next() 方法会在每次循环时调用,用于跳过下一个元素。remove() 方法用于移除上一个我们跳过的元素。对 remove() 方法的调用不会导致迭代器的失效,因此继续使用迭代器是安全的。这种方式在反向迭代时也是没问题的。

QMutableListIterator<int> i(list);
i.toBack();
while (i.hasPrevious()) {
    if (i.previous() % 2 != 0)
        i.remove();
}

如果仅仅想修改已存在元素的值,我们可以使用 setValue()。下列代码中,我们将所有大于 128 的值替换成 128:

QMutableListIterator<int> i(list);
while (i.hasNext()) {
    if (i.next() > 128)
        i.setValue(128);
}

remove() 一样, setValue() 对我们跳过的最后一个元素进行操作。如果我们向前迭代,这个元素就是迭代器之前的元素;如果我们向后迭代,这个元素就是迭代器之后的元素。

next() 方法返回的是列表中元素的非常量引用,对于简单的操作,我们并不需要调用 setValue()

QMutableListIterator<int> i(list);
while (i.hasNext())
    i.next() *= 2;

正如上面提到的,QLinkedListQVectorQSet 的迭代器的 API 和 QList 的完全一致。接下来我们来看看在某些方面不太一样的 QMapIterator,因为其用于迭代(键,值)对。

QListIterator 一样,QMapIterator 提供了 toFront(), toBack(), hasNext(), next(), peekNext(), hasPrevious(), previous()peekPrevious() 方法。我们可以对 next(), peekNext(), previous()peekPrevious() 返回的对象调用 key()value() 方法来获得键和值。

下列代码用于移除所有首都名以”city“结尾的(首都名,国家名)键值对。

QMap<QString, QString> map;
map.insert("Paris", "France");
map.insert("Guatemala City", "Guatemala");
map.insert("Mexico City", "Mexico");
map.insert("Moscow", "Russia");
...

QMutableMapIterator<QString, QString> i(map);
while (i.hasNext()) {
    if (i.next().key().endsWith("City"))
        i.remove();
}

QMapIterator 也提供了 key()value() 方法用于操作迭代器及迭代器上一个跳过的元素的键和值。举个例子,下列代码用于将 QMap 的内容拷贝到 QHash 中。

QMap<int, QWidget *> map;
QHash<int, QWidget *> hash;

QMapIterator<int, QWidget *> i(map);
while (i.hasNext()) {
    i.next();
    hash.insert(i.key(), i.value());
}

如果想要迭代遍历所有值相同的元素,我们可以使用 findNext()findPrevious()。这里的例子用于移除带有指定值的元素。

QMutableMapIterator<int, QWidget *> i(map);
while (i.findNext(widget))
    i.remove();

STL 风格迭代器

STL 风格迭代器在 Qt 2.0 中被引入,可用于 Qt 和 STL 的泛型算法,且为速度做了优化。

对于每一个容器类,同时提供了两种类型的 STL 风格迭代器:一种支持只读访问,另一种支持读写访问。

容器只读迭代器读写迭代器
QList, QQueueQList::const_iteratorQList::iterator
QLinkedListQLinkedList::const_iteratorQLinkedList::iterator
QVector, QStackQVector::const_iteratorQVector::iterator
QSetQSet::const_iteratorQSet::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

STL 风格迭代器的 API 以 数组指针为原型设计。例如,++ 运算符将迭代器向前移动至下一个元素,* 运算符返回迭代器指向的元素。实际上,对于 QVectorQStack 这类元素存储在连续内存的容器来说,iterator 类型仅仅是 T * 的别名,const_iteratorconst T * 的一个别名。

在接下来的讨论中,我们将重点关注 QListQMapQLinkedListQVectorQSet 的迭代器类型和QList有完全一样的接口,类似的,QHashQMap 的迭代器类型的接口也是相同的。

这是一个通过循环迭代有序遍历 QList<QString> 中的所有元素并将它们转成小写的常见写法:

QList<QString> list;
list << "A" << "B" << "C" << "D";

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    *i = (*i).toLower();

Java 风格迭代器不同,STL 风格迭代器直接指向元素本身。容器的 begin() 方法会返回一个指向容器第一个元素的迭代器,end() 方法返回的迭代器指向一个虚拟的元素,该元素位于容器最后一个元素的下一个位置。end() 标记了一个非法的位置,永远不要对其解引用。其通常被用作循环的结束条件。对于空列表,begin()end() 是相等的,因此我们永远不会执行循环。

下图用红色箭头展示了一个四个元素的列表容器中合法的迭代器位置。

STL Style Iterator

使用 STL 风格迭代器反向遍历可以通过反向迭代器实现

QList<QString> list;
list << "A" << "B" << "C" << "D";

QList<QString>::reverse_iterator i;
for (i = list.rbegin(); i != list.rend(); ++i)
    *i = i->toLower();
}

上面的代码片段中,我们通过一元运算符 * 来获取保存在指定迭代器位置的元素(此处类型为QString),并对其调用了 QString::toLower() 方法。大部分 C++ 编译器也同时支持i->toLower()这种写法,但也有一些不支持。

对于只读访问,你可以使用 const_iterator , constBegin()constEnd()。例如:

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

下表整理了 STL 风格迭代器的 API:

表达式行为
*i返回当前元素
++i向前移动迭代器至下一元素
i += n向前移动迭代器 n 次
--i向后移动迭代器至前一个元素
i -= n向后移动迭代器 n 次
i - j返回迭代器 i 和 j 间隔的元素个数

++-- 运算符既可以作为前缀( ++i--i) ,也可以作为后缀(i++i--)运算符。前缀版本先修改迭代器,然后返回修改后的迭代器的引用。后缀版本在修改迭代器之前先将其复制一份,然后返回副本。在返回值被忽略的表达式中,我们建议使用前缀版本,因为这样会略快一点。

对于非常量迭代器类型,一元运算符 * 的返回值可以作为赋值运算符的左侧。

对于 QMapQHash* 运算符返回一个元素的值,如果你想获取键,可以调用迭代器的 key() 方法。相对应的,迭代器类型也提供了 value() 用于获取值。下面是一个将 QMap 中所有元素打印到终端的例子:

QMap<int, int> map;
...
QMap<int, int>::const_iterator i;
for (i = map.constBegin(); i != map.constEnd(); ++i)
    qDebug() << i.key() << ':' << i.value();

正是因为隐式共享,调用一个返回容器的函数的开销不会很大。Qt API 中包含几十个返回值为 QListQStringList 的函数(例如 QSplitter::sizes() )。如果需要通过 STL 迭代器遍历这些返回值,你应当总是将返回的容器复制一份然后迭代其副本。例如:

// 正确
const QList<int> sizes = splitter->sizes();
QList<int>::const_iterator i;
for (i = sizes.begin(); i != sizes.end(); ++i)
    ...

// 错误
QList<int>::const_iterator i;
for (i = splitter->sizes().begin();
        i != splitter->sizes().end(); ++i)
    ...

如果函数返回的是一个容器的常量或非常量引用,那么是不存在这个问题的。

隐式共享迭代器问题

隐式共享给 STL 风格迭代器带来了另一个后果是:当一个容器的迭代器在使用时你应当避免复制该容器。迭代器指向了一个内部结构,当你复制容器时你需要特别小心的处理迭代器。比如:

QVector<int> a, b;
a.resize(100000); // 创建一个填充0的大数组.

QVector<int>::iterator i = a.begin();
// 迭代器i的错误用法:
b = a;
/*
    现在我们应当小心地使用迭代器`i`,因为 i 指向的是共享的数据。
    如果我们执行 *i = 4 那么我们可能改变共享的实例(两个数组共享)
    这个行为和 STL 容器是不同的。在 Qt 中不要这样做。
*/

a[0] = 5;
/*
    容器 a 现在已经和共享数据脱离,
    即使 i 之前是容器 a 的迭代器,但现在它是作为 b 的迭代器而存在。
    此时 (*i) == 0
*/

b.clear(); // 此时 i 彻底失效

int j = *i; // 未定义行为!
/*
    b 中的数据(即i 指向的)已经被释放,
    在 STL 容器中这是有明确定义的((*i) == 5),
    但对于 QVector 来说这样做很有可能导致崩溃。
*/

译注:STL 容器std::vector在调用clear()方法后内存不会被释放,因此迭代器并不会立即失效

上面的例子仅仅说明了QVector的问题,但实际上所有支持隐式共享的容器都存在该问题。

foreach 关键字

如果仅仅是需要有序迭代容器中的每个元素,你可以使用 Qt 提供的关键字 foreach。这个关键字对 C++ 语言的一个特定于 Qt 的补充,其通过预处理器实现。

使用的语法是:foreach(变量容器) 语句。下面是一个使用 foreach 迭代 QLinkedList<QString> 的例子:

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

和使用迭代器实现相同功能的代码相比,使用foreach的代码明显简洁很多。

QLinkedList<QString> list;
...
QLinkedListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

除了数据类型包含逗号(例如 QPair<int, int>)以外,用于迭代的变量可以在 foreach 语句中被定义:

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

和其他 C++ 循环结构类似,你可以使用大括号将循环体包围,也可以使用 break 跳出循环。

QLinkedList<QString> list;
...
foreach (const QString &str, list) {
    if (str.isEmpty())
        break;
    qDebug() << str;
}

对于 QMapQHashforeach 会自动访问(键,值)对中的值,因此你不需要再调用容器的 values() 方法(这样可能会产生不必要的复制,见后续说明)。如果你想要同时迭代键和值,可以使用迭代器(会更快),或者也可以先获取所有的键,再通过它们获取对应的值:

QMap<QString, int> map;
...
foreach (const QString &str, map.keys())
    qDebug() << str << ':' << map.value(str);

对于一个多值映射:

QMultiMap<QString, int> map;
...
foreach (const QString &str, map.uniqueKeys()) {
    foreach (int i, map.values(str))
        qDebug() << str << ':' << i;
}

当进入一个 foreach 循环,Qt 会自动产生一个容器的副本。如果在迭代过程中修改了容器,并不会影响到这次循环。(如果没有修改容器,副本依然会占用空间,但由于隐式共享的缘故,复制一个容器是非常快的)。

因为 foreach 会产生容器的副本,使用是个变量的非常量引用也是无法修改原容器的,它仅仅会影响副本,这可能不是你想要的。

一个对 Qt 的 foreach 循环的替代方案是 C++ 11 或更新标准中引入的基于范围的 for 循环。然而,基于范围的 for 循环可能强行导致 Qt 容器脱离,但 foreach 不会。由于使用 foreach 总是会复制一份容器,对 STL 容器来说这通常会导致一定的开销。如果不知道用哪个,建议对 Qt 容器选择 foreach,而对 STL 容器选择基于范围的 for 循环。

除了 foreach,Qt 还提供了一个 forever 伪关键字用于执行无限循环。

forever {
    ...
}

如果你担心命名空间污染,你可以在 .pro 文件中添加以下代码以禁用这些宏:

CONFIG += no_keywords

其他类似容器类

Qt 包含了在某些方面和容器相似的其他模板类。这些类没有提供迭代器,也无法在foreach关键字中使用。

  • QCache<Key, T> 提供了一个缓存,用于保存与键类型Key相关联的类型T的对象。
  • QContiguousCache 提供了一个高效的方式用于缓存那些通常以连续的方式访问的数据。
  • QPair<T1, T2> 保存了一对元素。

其他基于 Qt 的模板容器实现的非模板类型有 QBitArray, QByteArray, QStringQStringList

算法复杂度

算法复杂度关注的是当容器中元素数量增加时,每个函数有多快(或者说多慢)。例如,无论 QLinkedList 中的元素数量有多少,在其中间插入一个元素是一个极快的操作,然而在一个具有非常多的元素的 QVector 中间插入一个元素可能会非常慢,因为半数的元素需要在内存中移动一个位置。

为了描述算法复杂度,我们使用以下基于“大O”符号的术语:

  • 常量时间:O(1)。函数有常量时间复杂度表示无论容器中有多少元素,执行该函数的时间都是相等的。一个例子是 QLinkedList::insert());
  • 对数时间:O(log n)。函数有对数时间复杂度表示该函数的运行时间和容器中元素个数的对数成正比。一个例子是二分查找算法。
  • 线性时间:O(n)。函数有线性时间复杂度表示该函数的运行时间和容器中元素的个数成正比。一个例子是 QVector::insert()
  • 线性对数时间:O(n log n)。线性对数时间复杂度的函数要比线性复杂度的函数慢,且随着数量的增加差距会越来越大,但依然比平方时间的函数快。
  • 平方时间:O(n²)。函数有平方时间复杂度表示该函数的运行时间和容器中元素的个数的平方成正比。

下表总结了 Qt 线性容器类的算法复杂度。

线性查找插入头部追加尾部追加
QLinkedListO(n)O(1)O(1)O(1)
QListO(1)O(n)Amort. O(1)Amort. O(1)
QVectorO(1)Amort. O(n)O(n)Amort. O(1)

表中的 “Amort. ” 表示“均摊行为”。例如,“Amort. O(1)” 表示如果仅调用一次该方法,你可能耗费 O(n) 的时间,但如果多次调用(假设调用 n 次),平均下来复杂度将会是 O(1)。

下表总结了 Qt 关联容器的算法复杂度。

查找键插入
平均最坏情况平均最坏情况
QMap<Key, T>O(log n)O(log n)O(log n)O(log n)
QMultiMap<Key, T>O(log n)O(log n)O(log n)O(log n)
QHash<Key, T>Amort. O(1)O(n)Amort. O(1)O(n)
QSetAmort. O(1)O(n)Amort. O(1)O(n)

对于 QVectorQHashQSet,在尾部追加元素的时间复杂度均摊下来是 O(log n)。但如果在插入元素之前以计划插入的元素个数 n 为参数调用 QVector::reserve(), QHash::reserve()QSet::reserve(),复杂度将会降低至 O(1) 。下一节将会针对该问题做更深入的讨论。

增长策略

QVectorQStringQByteArray 使用连续内存保存元素;QList 维护了一个保存所有元素的指针(除非 T 本身是一个指针类型或一个指针大小的基本类型,这种情况下数组中保存的的是元素本身的值)的数组,用于提供基于索引的快速访问;QHash<Key, T> 内部有一个和大小元素个数成正比的哈希表。为了避免每次在尾部添加元素时重新分配内存,这些类通常会分配比实际需要要多的内存。

考虑下列代码,它用另一个 QString 构建出一个新的 QString

QString onlyLetters(const QString &in)
{
    QString out;
    for (int j = 0; j < in.size(); ++j) {
        if (in[j].isLetter())
            out += in[j];
    }
    return out;
}

我们通过每次追加一个字符的方式动态的构建了一个字符串。假设我们追加 15000 个字符到这个 QString 字符串,接下来会在已分配内存耗尽时触发 QString 进行 18 次内存重新分配,分别在已分配量为:4,8,12,16,20,52,116,244,500,1012,2036,4048,6132,8180,10228,12276,14324,16372时。最后,这个 QString 占用了 16372 个 Unicode 字符的空间,其中 15000 个被实际使用了。

上面的数字可能有些奇怪,这里是分配的指导原则。

  • QString 每次分配 4 个字符指导达到 20 个字符。
  • 从 20 到 4084 个字符,每次将当前的大小翻倍。更准确的说,是翻倍后再减去 12。(一些内存分配器在分配刚好两倍的内存时性能较差,因为它们需要使用每块内存块中的一些字节用于登记。
  • 从 4084 开始,每次分配将会在原来的基础上增加 2048 个字符大小(4096 字节)。这么做的意义是现代操作系统在重新分配内存时并不会复制全部的数据,而仅仅是简单地将物理内存页重新排序,只有第一页和最后一页的数据需要复制。

QByteArrayQList 使用和 QString 差不多的增长算法。

当数据类型支持通过 memcpy() 在内存中进行移动时(包括基本 C++ 类型,指针类型和 Qt 的隐式共享类),QVector 也使用相同的算法。但在数据类型只支持通过复制构造函数和析构函数进行移动时则使用不同的算法。在这种情况下,重新分配的开销会大的多,因此 QVector 将总是会在空间耗尽时直接申请两倍的内存,以减少重新分配的次数。

QHash<Key, T> 则是完全不同。QHash 内部的哈希表每次增长两倍,每次增长时,保存的元素将会重新分配到一个通过 qHash(key) % QHash::capacity()(簇序号)计算出来的新的簇中。此说明同样适用于 QSetQCache<Key, T>。

对于大部分的应用,Qt 提供的增长策略完全可以满足需要。如果你需要进行自定义调整,QVector, QHash<Key, T>, QSet, QStringQByteArray 提供了一个提供了三个方法用于检查和指定保存元素使用的内存量。

  • capacity() 用于返回已分配内存的元素个数(对于QHashQSet,返回的是哈希表的簇的个数)。
  • reserve(size) 用于显式的预分配 size 个元素大小的内存。
  • squeeze() 用于释放所有没有用来保存元素的内存。

如果预先知道容器要保存元素的大概数量,可以提前调用 reserve() 方法分配内存,最后在填充完容器后,再调用 squeeze() 来释放多余的预分配内存。

Reserved by leytou until 2020-07-31

Reserved by leytou until 2020-07-31

Reserved by froser until 2020-09-15

[TOC]

QCoreApplication 类

QCoreApplication类为没有UI的Qt程序提供了一个事件循环。

属性方法
头文件#include<QCoreApplication>
qmakeQT+=core
自从Qt 4.6
继承QObject
派生QGuiApplication

属性

属性类型属性类型
applicationNameQStringorganizationNameQString
applicationVersionQStringquitLockEnabledQString
organizationDomainQString

公共成员函数

详细说明

此类为那些没有GUI的应用程序提供消息循环。对于使用Qt但无GUI的程序,它们必须有且仅有一个QCoreApplication对象。对于GUI应用程序,请参见QGuiApplication。对于使用了Qt Widgets的模块,请参见QApplication

QCoreApplication包含主事件循环,这些来自于操作系统(如定时器、网络事件等)及其它来源的事件将由它来处理和派发。它同时也处理应用程序的初始化和析构,以及全系统和全程序的设置。

事件循环及事件处理

消息循环从调用exec()开始。长时间运行的一些操作也可以通过调用processEvents()让程序保持响应。

一般地,我们建议您尽可能早地在您的main()函数中创建QCoreApplication、QGuiApplicationQApplication。当消息循环退出时,例如当quit()被调用时,exec()才会返回。

我们也提供了一些便捷的静态函数。QCoreApplication对象能够通过instance()来获取。您可以通过sendEvent()来发送事件,以及通过postEvent()来投送事件。待处理的事件能通过removePostedEvents()来移除,亦可通过sendPostedEvents()来派发。

此类提供了一个槽函数quit()及一个信号aboutToQuit()。

程序和库路径

一个应用程序有一个applicationDirPath()和一个applicationFilePath()。库路径(参见QLibrary)能通过libraryPaths()被获取,且能通过setLibraryPaths()、addLibraryPath()和removeLibraryPath()来对它进行操作。

国际化和翻译

翻译文件能分别通过installTranslator()和removeTranslator()被加载和移除。您可以通过translate()来翻译应用中的字符串。QObject::tr()和QObject::trUtf8()这两个函数根据translate()来进行了实现。

访问命令行参数

您应该通过arguments()来获取传递给QCoreApplication构造函数的命令行参数。

注意:QCoreApplication将移除**-qmljsdebugger="..."选项。它会解析qmljsdebugger**参数,然后删除此选项及其参数。

对于一些更加高级的命令行参数的处理,请创建一个QCommandLineParser

区域设置

运行在Unix/Linux的Qt程序,将会默认使用系统的区域设置。这可能会导致在使用POSIX函数时发生冲突,例如,数据类型转换时由转换浮点数转换为字符串,由于不同区域符号的差异可能会导致一些冲突。为了解决这个问题,在初始化QGuiApplicationQApplication或QCoreApplication之后,需要马上调用POSIX函数setlocale(LC_NUMERIC, "C"),以重新将数字的格式设置为"C"-locale。

另请参阅QGuiApplication, QAbstractEventDispatcher, QEventLoop, [Semaphores Example](../../S/Semaphorse Example/Semaphores Example.md), 以及[Wait Conditions Example](../../W/Wait Conditions Example/Wait Conditions Example.md)。

属性文档

applicationName : QString

此属性保存应用程序的名字。

当使用空的构造函数初始化QSettings类的实例时,此属性被使用。这样一来,每次创建QSettings对象时,都不必重复此信息。

如果未设置,则应用程序名称默认为可执行文件名称(自5.0开始)。

访问函数:

QStringapplicationName()
voidsetApplicationName(const QString &application)

通知信号:

voidapplicationNameChanged()

另请参阅 organizationName, organizationDomain, applicationVersion, 以及 applicationFilePath()。

applicationVersion: QString

此属性保存应用程序的版本。

如果没有设置此属性,那么此属性将会被默认设置为平台相关的值,该值由主应用程序的可执行文件或程序包确定(自Qt 5.9起):

平台
Windows (经典桌面)VERSIONINFO 资源中的 PRODUCTVERSION 参数
Windows通用应用平台(UWP)应用程序包中清单文件的版本属性
macOS, iOS, tvOS, watchOS信息属性列表中的CFBundleVersion属性
AndroidAndroidManifest.xml清单中的android:versionName属性

在其他平台上,此属性默认值为空字符串。

此属性自Qt 4.4引入。

访问函数:

QStringapplicationVersion()
voidsetApplicationVersion(const QString &version)

通知信号:

voidapplicationVersionChanged()

另请参阅applicationName, organizationName, 以及organizationDomain

organizationDomain: QString

此属性保存编写此应用程序的组织的Internet域。

当使用空的构造函数初始化QSettings类的实例时,此属性被使用。这样一来,每次创建QSettings对象时,都不必重复此信息。

在Mac上,如果organizationDomain()不是一个空值,那么QSettings将会使用它;否则它将会使用organizatioName()。在其他平台上,QSettingsorganizationName()作为组织名来使用。

访问函数:

QStringorganizationDomain()
voidsetOrganizationDomain(const QString &orgDomain)

通知信号:

voidorganizationDomainChanged()

另请参阅 organizationName, applicationName, 以及applicationVersion

organizationName: QString

此属性保存编写此应用程序的组织名。

当使用空的构造函数初始化QSettings类的实例时,此属性被使用。这样一来,每次创建QSettings对象时,都不必重复此信息。

在Mac上,如果organizationDomain()不是一个空值,那么QSettings将会使用它;否则它将会使用organizatioName()。在其他平台上,QSettingsorganizationName()作为组织名来使用。

访问函数:

QStringorganizationName()
voidsetOrganizationName(const QString &orgName)

通知信号:

voidorganizationNameChanged()

另请参阅 applicationDomainapplicationName

quitLockEnabled: bool

此属性保存使用QEventLoopLocker是否能退出的特性。

默认值是true

访问函数:

boolisQuitLockEnabled()
voidsetQuitLockEnabled(bool enabled)

另请参阅 QEventLoopLocker

成员函数文档


QCoreApplication::QCoreApplication(int &argc, char **argv)

构造一个Qt内核程序。所谓内核程序,就是没有图形用户界面的程序。这样的程序使用控制台,或者是作为服务进程运行着。

argcargv参数将会被应用程序处理,将其转换为一种更加便捷的形式,并可以通过arguments()来获取。

警告argcargv这两个值所指向的内存,必须在整个QCoreApplication生命周期内有效。另外,agrc必须要大于0,且argv必须至少包含一个合法的字符串。


void QCoreApplication::aboutToQuit() [signal]

当程序即将退出主消息循环时,如当消息循环嵌套层数降为0时,此事件被发射。它可能发生在应用程序中调用quit()之后,亦发生在关闭整个桌面会话时。

注意:这是一个私有信号。它能够被连接,但是用户无法发射它。

另请参阅 quit()。


void QCoreApplication::quit() [static slot]

告知程序以返回值0来退出。等效于调用 QCoreApplication::exit(0)。

一般我们将quit()槽连接到QGuiApplication::lastWindowClosed()信号,您同样可以将此槽连接到QActionQMenuQMenuBarQAbstractButton::clicked()信号上。

将信号以QueuedConnection参数连接此槽是一个不错的实践。如果连接了此槽的一个信号(未在队列中的)在控制流程进入主消息循环前(如在int main中调用exec()之前)被发射,那么这个槽不会有任何效果,应用程序也不会退出。使用队列连接方式能保证控制路程进入主消息循环后,此槽才会被触发。

例如:

QPushButton *quitButton = new QPushButton("Quit");
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection);

另请参阅 exit(), aboutToQuit(), and QGuiApplication::lastWindowClosed()。


QCoreApplication::~QCoreApplication() [virtual]

销毁QCoreApplication对象。


void QCoreApplication::addLibraryPath(const QString &path) [static]

path添加到库路径开头,保证它先会被库搜索到。如果path为空或者已经存在于路径列表,那么路径列表保持不变。

默认的路径列表只包含一个条目,即插件安装路径。默认的插件安装文件夹是INSTALL/plugins,其中INSTALL是Qt安装文件夹。

QCoreApplication被销毁后,这些库路径将会被重设为默认值。

另请参阅 removeLibraryPath(), libraryPaths(), and setLibraryPaths().


QString QCoreApplication::applicationDirPath() [static]

返回包含此可执行文件的文件夹路径。

例如,您已经在C:\Qt安装了Qt,然后运行regexp示例,那么这个函数会返回"C:/Qt:/examples/tools/regexp"。

在macOS和iOS上,它会指向实际包含可执行文件的目录,该目录可能在一个应用程序包内(如果是以应用程序包形式存在)。

警告:在Linux上,这个函数会尝试从/proc获取文件路径。如果失败了,那么它假设argv[0]包含了可执行文件的绝对路径。此函数同样也假设了应用程序不会改变当前路径。

另请参阅 applicationFilePath()。


QString QCoreApplication::applicationFilePath() [static]

返回包含此可执行文件的文件路径。

例如,您已经在/usr/local/qt目录安装了Qt,然后运行regexp示例,那么这个函数会返回"/usr/local/qt/examples/tools/regexp/regexp"。

警告:在Linux上,这个函数会尝试从/proc获取文件路径。如果失败了,那么它假设argv[0]包含了可执行文件的绝对路径。此函数同样也假设了应用程序不会改变当前路径。

另请参阅 applicationDirPath()。

qint64 QCoreApplication::applicationPid() [static]


返回当前应用程序的进程ID。

此函数自Qt 4.4引入。


QStringList QCoreApplication::arguments() [static]

返回命令行参数列表。

一般情况下,arguments().at(0)表示可执行文件名,arguments().at(1)是第一个参数,arguments().last()是最后一个参数。请见下面关于Windows的注释。

调用这个函数需要花费很多时间——您应该在解析命令行时,将结果缓存起来。

警告: 在Unix下,这个参数列表由main()函数中的argc和argv参数生成。argv中的字符串数据将会通过QString::fromLocal8Bit()来解析,因此,在Latin1的区域环境下,是不可能来传递日语的命令行的,其他情况以此类推。大部分现代Unix系统没有此限制,因为它们是基于Unicode的。

在Windows下,这个参数列表,只有在构造函数中传入了修改的argc和argv时,才会从这个argc和argv中解析。这种情况下,就会出现编码问题。

如果不是上述情况,那么arguments()将会从GetCommandLine()中构造。此时arguments().at(0)在Windows下未必是可执行文件名,而是取决于程序是如何被启动的。

此函数自Qt 4.1引入。

另请参阅 applicationFilePath()和QCommandLineParser


bool QCoreApplication::closingDown() [static]

如果application对象正在被销毁中,则返回true,否则返回false。

另请参阅 startingUp()。


bool QCoreApplication::event(QEvent *e) [override virtual protected]

重写了:QObject::event(QEvent* e)。


QAbstractEventDispatcher *QCoreApplication::eventDispatcher() [static]

返回指向主线程事件派发器的指针。如果线程中没有事件派发器,则返回nullptr

另请参阅 setEventDispatcher()。


int QCoreApplication::exec() [static]

进入主消息循环,直到exit()被调用。其返回值是为exit()传入的那个参数(如果是调用quit(),等效于调用exit(0))。

通过此函数来开始事件循环是很有必要的。主线程事件循环将从窗口系统接收事件,并派发给应用程序下的窗体。

为了能让您的程序在空闲时来处理事件(在没有待处理的事件时,通过调用一个特殊的函数),可以使用一个超时为0的QTimer。可以使用processEvents()来跟进一步处理空闲事件。

我们建议您连接aboutToQuit()信号来做一些清理工作,而不是将它们放在main函数中。因为在某些平台下,exec()可能不会返回。例如,在Windows下,当用户注销时,系统将在Qt关闭所有顶层窗口后才终止进程。因此,不能保证程序有时间退出其消息循环来执行main函数中exec()之后的代码。

另请参阅 quit(),exit(), processEvent()和QApplication::exec()。


void QCoreApplication::exit(int returnCode = 0) [static]

告诉程序需要退出了,并带上一个返回值。

在此函数被调用后,程序将离开主消息循环,并且从exec()中返回。其返回值就是returnCode。如果消息循环没有运行,那么此方法什么都不做。

一般我们约定0表示成功,非0表示产生了一个错误。

将信号以QueuedConnection参数连接此槽是一个不错的实践。如果连接了此槽的一个信号(未在队列中的)在控制流程进入主消息循环前(如在int main中调用exec()之前)被发射,那么这个槽不会有任何效果,应用程序也不会退出。使用队列连接方式能保证控制路程进入主消息循环后,此槽才会被触发。

另请参阅 quit()和exec()。


void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)

在主线程为应用程序所能接收到的原生事件安装一个事件过滤器。

事件过滤器filterObj通过nativeEventFilter()来接收事件。它可以接收到主线程所有的原生事件。

如果某个原生事件需要被过滤或被屏蔽,那么QAbstractNativeEventFilter::nativeEventFilter需要返回true。如果它需要使用Qt默认处理流程,则返回false:那么接下来这个原生事件则会被翻译为一个QEvent,并且由Qt的标准事件过滤器来处理。

如果有多个事件过滤器被安装了,那么最后安装的过滤器将会被最先调用。

注意: 此处设置的过滤器功能接收原生事件,即MSG或XCB事件结构。

注意: 如果设置了Qt::AA_PluginApplication属性,那么原生事件过滤器将会被屏蔽。

为了最大可能保持可移植性,您应该总是尽可能使用QEventQObject::installEventFilter()。

另请参阅 QObject::installEventFilter()。


bool QCoreApplication::installTranslator(QTranslator *translationFile) [static]

translationFile添加到翻译文件列表,它将会被用于翻译。

您可以安装多个翻译文件。这些翻译文件将会按照安装顺序的逆序被搜索到,因此最近添加的翻译文件会首先被搜索到,第一个安装的搜索文件会最后被搜索。一旦翻译文件中匹配了一个字符串,那么搜索就会终止。

安装、移除一个QTranslator,或者更改一个已经安装的QTranslator将会为QCoreApplication实例产生一个LanguageChange事件。一个QApplication会将这个事件派发到所有的顶层窗体,使用tr()来传递用户可见的字符串到对应的属性设置器,通过这种方式来重新实现changeEvent则可以重新翻译用户的界面。通过Qt设计师(Qt Designer)生成的窗体类提供了一个retranslateUi()可以实现上述效果。

函数若执行成功则返回true,失败则返回false。

另请参阅 removeTranslator(),translate(),QTranslator::load()和动态翻译


QCoreApplication* QCoreApplication::instance() [static]

返回程序的QCoreApplication (或QGuiApplication/QApplication)实例的指针。


bool QCoreApplication::isSetuidAllowed() [static]

如果在UNIX平台中,允许应用程序使用setuid,则返回true。

此函数自Qt 5.3引入。

另请参阅 QCoreApplication::setSetuidAllowed()。


QStringList QCoreApplication::libraryPaths() [static]

返回一个路径列表,其中的路径表示动态加载链接库时的搜索路径。

此函数的返回值也许会在QCoreApplication创建之后改变,因此不建议在QCoreApplication创建之前调用。应用程序所在的路径(工作路径),如果是已知的,那么它会被放入列表中。为了能知道这个路径,QCoreApplication必须要在创建时使用argv[0]来表示此路径。

Qt提供默认的库搜索路径,但是它们同样也可以通过qt.conf文件配置。在此文件中所指定的路径会覆盖默认路径。注意如果qt.conf文件存在于应用程序所在的文件夹目录下,那么直到QCoreApplication被创建时它才可以被发现。如果它没有被发现,那么调用此函数仍然返回默认搜索路径。

如果插件存在,那么这个列表会包含插件安装目录(默认的插件安装目录是 INSTALL/plugins,其中INSTALL是Qt所安装的目录。用分号分隔的QT_PLUGIN_PATH环境变量中的条目一定会被添加到列表。插件安装目录(以及它存在)在应用程序目录已知时可能会被更改。

如果您想遍历列表,可以使用foreach伪关键字:

foreach (const QString &path, app.libraryPaths())
    do_something(path);

另请参阅 setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary , 以及 如何创建Qt插件


bool QCoreApplication::notify(QObject receiver, QEvent event) [virtual]

将事件发送给接收者:receiver->event(event)。其返回值为接受者的事件处理器的返回值。注意这个函数将会在任意线程中调用,并将事件转发给任意对象。

对于一些特定的事件(如鼠标、键盘事件),如果事件处理器不处理此事件(也就是它返回false),那么事件会被逐级派发到对象的父亲,一直派发到顶层对象。

处理事件有5种不同的方式:重写虚函数只是其中一种。所有的五种途径如下所示:

  1. 重写paintEvent(),mousePressEvent()等。这个是最通用、最简单但最不强大的一种方法。
  2. 重写此函数。这非常强大,提供了完全控制,但是一次只能激活一个子类。
  3. 将一个事件过滤器安装到QCoreApplication。这样的一个事件过滤器可以处理所有窗体的所有事件,就像是重写了notify()函数这样强大。此外,您还可以提供多个应用级别全局的事件过滤器。全局事件过滤器甚至可以接收到那些不可用窗体的鼠标事件。注意程序的事件过滤器仅能响应主线程中的对象。
  4. 重写QObject::event()(就像QWidget那样)。如果您是这样做的,您可以接收到Tab按键,及您可以在任何特定窗体的事件过滤器被调用之前接收到事件。
  5. 在对象上安装事件过滤器。这样的事件过滤器将可以收到所有事件,包括Tab和Shift+Tab事件——只要它们不更改窗体的焦点。

未来规划:在Qt 6中,这个函数不会响应主线程之外的对象。需要该功能的应用程序应同时为其事件检查需求找到其他解决方案。该更改可能会扩展到主线程,因此不建议使用此功能。

注意:如果您重写此函数,在您的应用程序开始析构之前,您必须保证所有正在处理事件的线程停止处理事件。这包括了您可能在用的其他库所创建的线程,但是不适用于Qt自己的线程。

另请参阅QObject::event()和installNativeEventFilter()。


void QCoreApplication::postEvent(QObject* receiver, QEvent* event, int priority = Qt::NormalEventPriority) [static]

添加一个event事件,其中receiver表示事件的接收方。事件被添加到消息队列,并立即返回。

被添加的事件必须被分配在堆上,这样消息队列才能接管此事件,并在它被投送之后删除它。当它被投递之后,再来访问此事件是不安全的。

当程序流程返回到了主事件循环时,所有的队列中的事件会通过notify()来发送。

队列中的事件按照priority降序排列,这意味着高优先级的事件将排列于低优先级之前。优先级priority可以是任何整数,只要它们在INT_MAXINT_MIN之闭区间内。相同优先级的事件会按照投送顺序被处理。

注意:此函数是线程安全的。

此函数自Qt 4.3引入。

另请参阅sendEvent(),notify(),sendPostedEvents(),和Qt::EventPriority


void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents) [static]

根据flags处理调用线程的所有待处理事件,直到没有事件需要处理。

您可以在您程序进行一项长时间操作的时候偶尔调用此函数(例如拷贝一个文件时)。

如果您在一个本地循环中持续调用这个函数,而不是在消息循环中,那么DeferredDelete事件不会被处理。这会影响到一些窗体的行为,例如QToolTip,它依赖DeferredDelete事件。以使其正常运行。一种替代方法是从该本地循环中调用sendPostedEvents()。

此函数只处理调用线程的事件,当所有可处理事件处理完毕之后返回。可用事件是在函数调用之前排队的事件。这意味着在函数运行时投送的事件将会排队到下一轮事件处理为止。

注意:此函数是线程安全的。

另请参阅exec(),QTimerQEventLoop::processEvents(),flush()和sendPostedEvents()。


void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents, int ms) [static]

此函数重写了processEvents()。

此函数将用ms毫秒为调用线程处理待处理的事件,或者直到没有更多事件需要处理。

您可以在您程序进行一项长时间操作的时候偶尔调用此函数(例如拷贝一个文件时)。

此函数只处理调用线程的事件。

注意:不像processEvents()的重写,这个函数同样也处理当函数正在运行中时被投送的事件。),QTimer,QEventLoop::processEvents()。

另请参阅exec(),QTimerQEventLoop::processEvents()。


void QCoreApplication::removeLibraryPath(const QString &path) [static]

从库的搜索路径列表中移除path。如果path是空的,或者不存在于列表,则列表不会改变。

QCoreApplication被析构时,此列表会被还原。

另请参阅exec(),QTimerQEventLoop::processEvents()。


void QCoreApplication::removeNativeEventFilter(QAbstractNativeEventFilter *filterObject)

从此实例中移除filterObject事件过滤器。如果这个事件过滤器没有被安装,则什么也不做。

当此实例被销毁时,所有的事件过滤器都会自动被移除。

任何时候——甚至正在事件过滤被激活时(通过nativeEventFilter()函数)——移除一个事件过滤器都是安全的。

此函数自Qt 5.0引入。

另请参阅installNativeEventFilter()。


void QCoreApplication::removePostedEvents(QObject *receiver, int eventType = 0) [static]

移除所指定的 eventType 类型且由postEvent()所添加的事件。

这些事件不会被派发,而是直接从队列中移除。您从来都不需要调用此方法。如果您确实调用了它,那么请注意杀掉事件可能会影响 receiver 的不变性(invariant)。

如果接收者为nullptr,那么所有对象将会移除 eventType 所指定的所有事件。如果 eventType 为0,那么receiver的所有事件将会被移除。自始自终,您都不应将 0 传递给 eventType

注意:此函数是线程安全的。

此函数自Qt 4.3引入。


bool QCoreApplication::removeTranslator(QTranslator *translationFile) [static]

从此应用程序使用的翻译文件列表中删除翻译文件 translationFile 。 (不会在文件系统中删除此翻译文件。)

该函数成功时返回 true ,失败时返回 false 。

另请参阅installTranslator()translate(),与 QObject::tr()


bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event) [static]

通过函数 notify() 将事件 event 直接发送至接收对象 receiver 。返回从事件处理对象得到的返回值。

事件 不会 在发送之后删除掉。通常的方法是在栈上创建事件,例如:

QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
QApplication::sendEvent(mainWindow, &event);

另请参阅postEvent()notify()


void QCoreApplication::sendPostedEvents(QObject *receiver = nullptr, int event_type = 0) [static]

立刻分派所有先前通过 QCoreApplication::postEvent() 进入队列的事件。这些事件是针对接收对象的,且事件类型为 event_type

该函数不会对来自窗口系统的事件进行分派,如有需求请参考 processEvents()

如果接收对象指针为 nullptrevent_type 的所有事件将分派到所有对象。如果 event_type 为 0 ,所有事件将发送到接收对象 receiver

注意: 该方法必须由其 QObject 参数 receiver 所在的线程调用。

另请参阅flush()postEvent()


void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on = true) [static]

如果 on 为 true ,则设置属性 attribute;否则清除该属性。

**注意:**在创建 QCoreApplication 实例之前,一些应用程序的属性必须要设置。 有关更多信息,请参考 Qt::ApplicationAttribute 文档。

另请参阅testAttribute()


void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) [static]

将主线程的事件分派器设置为 eventDispatcher 。只有在还没有安装事件分派器的情况下,也就是在实例化 QCoreApplication 之前,才可以进行设置。此方法获取对象的所有权。

另请参阅eventDispatcher()


void QCoreApplication::setLibraryPaths(const QStringList &paths) [static]

将加载库时要搜索的目录列表设置为 paths。现有的所有路径将被删除,路径列表将从参数 paths 中获取。

当实例 QCoreApplication 被析构时,库路径将设置为默认值。

另请参阅libraryPaths()addLibraryPath()removeLibraryPath()QLibrary


void QCoreApplication::setSetuidAllowed(bool allow) [static]

allow 为 true,允许程序在 UNIX 平台上运行 setuid 。

allow 为 false (默认值),且 Qt 检测到程序使用与实际用户id不同的有效用户id运行,那么在创建 QCoreApplication 实例时程序将中止。

Qt 受攻击面较大,因此它并不是一个恰当 setuid 程序解决方案。 不过,出于历史原因,可能某些程序仍需要这种方式运行。 当检测到此标志时,可防止 Qt 中止应用程序。须在创建 QCoreApplication 实例之前将其进行设置。

**注意:**强烈建议不要打开此选项,它会带来安全风险。

此函数自Qt 5.3引入。

另请参阅isSetuidAllowed()


bool QCoreApplication::startingUp()

如果应用程序对象尚未创建,则返回 true ;否则返回 false

另请参阅closingDown()


bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute) [static]

如果设置了属性 attribute ,返回 true ;否则返回 false 。

另请参阅setAttribute()


QString QCoreApplication::translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1) [static]

搜索最近到首次安装的翻译文件,查询翻译文件中 sourceText 对应的翻译内容,返回其结果。

QObject::tr() 作用相同且使用更便捷。

context 通常为类名(如 "MyDialog"),sourceText 则是英文文本或简短的识别文本。

disambiguation 为一段识别字符串,用于同一上下文中不同角色使用相同的 sourceText 。它的默认值为 nullptr

有关上下文、消除歧义和注释的更多信息,请参阅 QTranslatorQObject::tr() 文档。

n%n 一并使用以便支持复数形式。详见 QObject::tr()

如果没有任何翻译文件包含 contextsourceText 的翻译内容,该函数则返回 QString 包裹的 sourceText

此函数非虚函数。您可以子类化 QTranslator 来使用其他翻译技术。

**注意:**此函数线程安全。

另请参阅QObject::tr()installTranslator()removeTranslator(),与 translate()。

相关非成员函数


void qAddPostRoutine(QtCleanUpFunction ptr)

添加一个全局例程,它将在 QCoreApplication 析构函数中调用。这个函数通常用来作为在程序范围功能内,添加程序清除例程的函数。

清除例程的调用顺序与添加例程的顺序相反。

参数 ptr 指定的函数应既没有参数,也没有返回值,例如:

static int *global_ptr = nullptr;

static void cleanup_ptr()
{
    delete [] global_ptr;
    global_ptr = nullptr;
}

void init_ptr()
{
    global_ptr = new int[100];      // allocate data
    qAddPostRoutine(cleanup_ptr);   // delete later
}

注意,对于应用程序或模块范围的清理,qAddPostRoutine() 通常不太合适。例如,若程序被分割成动态加载的模块,那么相关的模块可能在 QCoreApplication 的析构函数调用之前就卸载了。在这种情况下,如果仍想使用 qAddPostRoutine() ,可以使用 qRemovePostRoutine() 来防止 QCoreApplication 的析构函数调用一个例程。举个例子,在模块卸载前调用 qRemovePostRoutine() 。

对于模块或库,使用引用计数初始化管理器,或者 Qt 对象树删除机制可能会更好。下面是一个私有类使用对象树机制正确调用清除函数的一个例子:

class MyPrivateInitStuff : public QObject
{
public:
    static MyPrivateInitStuff *initStuff(QObject *parent)
    {
        if (!p)
            p = new MyPrivateInitStuff(parent);
        return p;
    }

    ~MyPrivateInitStuff()
    {
        // cleanup goes here
    }

private:
    MyPrivateInitStuff(QObject *parent)
        : QObject(parent)
    {
        // initialization goes here
    }

    MyPrivateInitStuff *p;
};

通过选择正确的父对象,正常情况下可以在正确的时机清理模块的数据。

注意: 函数自 Qt 5.10 已线程安全

注意: 该函数线程安全

另请参阅qRemovePostRoutine()


void qRemovePostRoutine(QtCleanUpFunction ptr)

注意: 函数自 Qt 5.10 已线程安全

注意: 该函数线程安全

此函数自 Qt 5.3 引入。

另请参阅qAddPostRoutine()

宏文档


Q_COREAPP_STARTUP_FUNCTION(QtStartUpFunction ptr)

添加一个全局函数,它将在 QCoreApplication 的构造函数中调用。这个宏通常用于为程序范围内的功能初始化库,无需应用程序调用库进行初始化。

参数 ptr 指定的函数应既没有参数,也没有返回值,例如:

// Called once QCoreApplication exists
static void preRoutineMyDebugTool()
{
    MyDebugTool* tool = new MyDebugTool(QCoreApplication::instance());
    QCoreApplication::instance()->installEventFilter(tool);
}

Q_COREAPP_STARTUP_FUNCTION(preRoutineMyDebugTool)

注意,启动函数将在 QCoreApplication 构造后,在任何 GUI 初始化前调用。如果函数中需要GUI代码,请使用计时器(或队列动态调用),在后面的事件循环中执行初始化。

如果删除了 QCoreApplication 并创建了另一个 QCoreApplication ,将再次调用启动函数。

**注意:**此宏不适用于静态链接到应用程序中的库代码中使用,因为链接器可能会删除该函数,使其根本不会被调用。

**注意:**此函数是可重入的

此函数自 Qt 5.1 引入。


Q_DECLARE_TR_FUNCTIONS(context)

Q_DECLARE_TR_FUNCTIONS() 宏使用以下签名声明并实现了两个转换函数 tr()trUtf8()

static inline QString tr(const char *sourceText,
                         const char *comment = nullptr);
static inline QString trUtf8(const char *sourceText,
                             const char *comment = nullptr);

如果您想在不继承 QObject 的类使用 QObject::tr() 或者 QObject::Utf8() ,这个宏就非常适用。

Q_DECLARE_TR_FUNCTIONS() 宏必须写在类的第一行(在第一个 public: 或 protected: 之前),例如:

class MyMfcView : public CView
{
    Q_DECLARE_TR_FUNCTIONS(MyMfcView)

public:
    MyMfcView();
    ...
};

通常 context 参数为类名,不过也可以是任何文本。

另请参阅Q_OBJECTQObject::tr(),与 QObject::trUtf8()

[TOC]

QDate Class

属性方法
头文件#include <QDate>
qmakeQT += core

注意: 该类提供的所有函数都是可重入的。

公共成员类型

类型名称
enumMonthNameType{ DateFormat, StandaloneFormat }

公共成员函数

类型函数名
QDate(int y, int m, int d)
QDate()
QDateaddDays(qint64 ndays) const
QDateaddMonths(int nmonths, QCalendar cal) const
QDateaddMonths(int nmonths) const
QDateaddYears(int nyears, QCalendar cal) const
QDateaddYears(int nyears) const
intday(QCalendar cal) const
intday() const
intdayOfWeek(QCalendar cal) const
intdayOfWeek() const
intdayOfYear(QCalendar cal) const
intdayOfYear() const
intdaysInMonth(QCalendar cal) const
intdaysInMonth() const
intdaysInYear(QCalendar cal) const
intdaysInYear() const
qint64daysTo(const QDate &d) const
QDateTimeendOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const
QDateTimeendOfDay(const QTimeZone &zone) const
voidgetDate(int *year, int *month, int *day) const
boolisNull() const
boolisValid() const
intmonth(QCalendar cal) const
intmonth() const
boolsetDate(int year, int month, int day)
boolsetDate(int year, int month, int day, QCalendar cal)
QDateTimestartOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const
QDateTimestartOfDay(const QTimeZone &zone) const
qint64toJulianDay() const
QStringtoString(Qt::DateFormat format = Qt::TextDate) const
QStringtoString(const QString &format) const
QStringtoString(const QString &format, QCalendar cal) const
QStringtoString(QStringView format) const
QStringtoString(QStringView format, QCalendar cal) const
intweekNumber(int *yearNumber = nullptr) const
intyear(QCalendar cal) const
intyear() const
booloperator!=(const QDate &d) const
booloperator<(const QDate &d) const
booloperator<=(const QDate &d) const
booloperator==(const QDate &d) const
booloperator>(const QDate &d) const
booloperator>=(const QDate &d) const

静态公共成员

类型函数名
QDatecurrentDate()
QDatefromJulianDay(qint64 jd)
QDatefromString(const QString &string, Qt::DateFormat format = Qt::TextDate)
QDatefromString(const QString &string, const QString &format)
QDatefromString(const QString &string, const QString &format, QCalendar cal)
boolisLeapYear(int year)
boolisValid(int year, int month, int day)

相关非成员函数

类型函数名
QDataStream &operator<<(QDataStream &out, const QDate &date)
QDataStream &operator>>(QDataStream &in, QDate &date)

详细描述

无论系统的日历和地域设置如何,一个QDate对象代表特定的一天。它可以告诉您某一天的年、月、日,其对应着格里高利历或者您提供的QCalendar

一个QDate对象一般由显式给定的年月日创建。注意QDate将1~99的年数保持,不做任何偏移。静态函数currentDate()会创建一个从系统时间读取的QDate对象。显式的日期设定也可以使用 setDate()。fromString() 函数返回一个由日期字符串和日期格式确定的日期。

year()、month()、day() 函数可以访问年月日。另外,还有 dayOfWeek()dayOfYear() 返回一周或一年中的天数。文字形式的信息可以通过 toString()获得。天数和月数可以由 QLocale 类映射成文字。

QDate 提供比较两个对象的全套操作,小于意味着日期靠前。

您可以通过 addDays() 给日期增减几天,同样的还有 addMonths()、addYears() 增减几个月、几年。daysTo() 函数返回两个日期相距的天数。

daysInMonth() 和 daysInYear() 函数返回一个月、一年里有几天。isLeapYear() 用于判断闰年。

特别注意

  • 年数没有0 第0年的日期是非法的。公元后是正年份,公元前是负年份。QDate(1, 1, 1) 的前一天是 QDate(-1, 12, 31)

  • 合法的日期范围 日期内部存储为儒略日天号,使用连续的整数记录天数,公元前4714年11月24日是格里高利历第0天(儒略历的公元前4713年1月1日)。除了可以准确有效地表示绝对日期,此类也可以用来做不同日历系统的转换。儒略历天数可以通过 QDate::toJulianDay() 和 QDate::fromJulianDay()读写。 由于技术原因,储存的儒略历天号在 -784350574879~784354017364 之间,大概是公元前2亿年到公元后2亿年之间。

另请参阅:QTimeQDateTimeQCalendarQDateTime::YearRangeQDateEditQDateTimeEditQCalendarWidget

成员类型文档

enum QDate::MonthNameType

此枚举描述字符串中月份名称的表示类型

常量数值描述
QDate::DateFormat0用于日期到字符串格式化。
QDate::StandaloneFormat1用于枚举月份和一周七天。通常单独的名字用首字母大写的单数形式书写。

此枚举在Qt 4.5中引入或修改。

成员函数文档

QString QDate::toString(QStringView format) const

QString QDate::toString(QStringView format, QCalendar cal) const

QString QDate::toString(const QString &format) const

QString QDate::toString(const QString &format, QCalendar cal) const

返回字符串形式的日期。 参数format控制输出的格式。如果传入参数cal, 它决定了使用的日历系统,默认是格里高利历。

日期格式的表示如下:

占位符输出格式
d无占位0的日期 (1 to 31)
dd有占位0的日期 (01 to 31)
ddd简写的一周七天名称(例如 'Mon' to 'Sun')。使用系统地域设置来格式化, 也就是 QLocale::system()
dddd长版的一周七天名称 (例如 'Monday' to 'Sunday')。使用系统地域设置来格式化, 也就是 QLocale::system()
M无占位0的月份 (1 to 12)
MM有占位0的月份 (01 to 12)
MMM缩写的月份名称 (例如 'Jan' to 'Dec')。使用系统地域设置来格式化, 也就是 QLocale::system()
MMMM长版的月份名称 (例如 'January' to 'December')。使用系统地域设置来格式化, 也就是 QLocale::system()
yy两位数年份 (00 to 99)
yyyy四位数年份。 如果是负数,加上符号是五个字符

单引号包裹的内容将会一字不差地放进输出到字符串中(不带外面的单引号),尽管包含上述格式占位符。连续两个单引号('')会被转义成一个单引号输出。所有其他字符不会被转义,将原封不动输出。

没有分隔符的多个占位符(例如 "ddMM")受支持,但要慎用。因为结果的可读性不好,容易引发歧义(例如难以区分“dM”的输出"212"是清2.12还是21,2)

假设今天是1969年7月20日,下面是一些格式字符串的例子

格式结果
dd.MM.yyyy20.07.1969
ddd MMMM d yySun July 20 69
'The day is' ddddThe day is Sunday

如果日期非法,会返回空字符串。

注意: 如果需要本地化的日期表达, 请使用 QLocale::system().toString(),因为 QDate 将在 Qt 6 使用英文表达(C语言风格)。

另请参阅:fromString()、QDateTime::toString()、QTime::toString() 和 QLocale::toString()。


QDateTime QDate::endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const

QDateTime QDate::endOfDay(const QTimeZone &zone) const

返回这一天的最后一刻的时间。通常来说,是午夜前1ms:然而,如果时区转换让这一天跨过午夜(如夏令时),返回的是真实的最后一刻时间。这种情况只可能在使用时区参数QTimeZone zone或者本地时间参数 Qt::LocalTime spec时发生。

参数 offsetSeconds 会被忽略,除非参数 specQt::OffsetFromUTC,其表示出了时区信息。如果UTC和那个时区间没有过渡,一天的结束是 QTime(23, 59, 59, 999)。

在罕见的日期被整体跳过(只在从东向西跨越国际日期变更线时),返回可能是非法的。将 Qt::TimeZone 作为 spec 参数传递 (而不是一个 QTimeZone) 也会造成非法结果,如果那一时刻超过了 QDateTime 的表示范围。

函数在 Qt 5.14 中引入。

另请参阅:startOfDay()。


QDateTime QDate::startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const

QDateTime QDate::startOfDay(const QTimeZone &zone) const

返回一天的开始时刻。通常来说应该是午夜那一时刻:然而,如果时区转换让这一天跨过午夜(如夏令时),返回的是真实的最早的一刻时间。这种情况只可能在使用时区参数QTimeZone zone或者本地时间参数 Qt::LocalTime spec时发生。

参数 offsetSeconds 会被忽略,除非参数 specQt::OffsetFromUTC,其表示出了时区信息。如果UTC和那个时区间没有过渡,一天的结束是 QTime(0, 0)。

在罕见的日期被整体跳过(只在从东向西跨越国际日期变更线时),返回可能是非法的。

Qt::TimeZone 作为 spec 参数传递 (而不是一个 QTimeZone) 也会造成非法结果,如果那一时刻超过了 QDateTime 的表示范围。

函数在 Qt 5.14 中引入。

另请参阅:endOfDay()。


QDate::QDate(int y, int m, int d)

从年月日构造对象,使用格里高利历。如果日期非法,对象不会修改,且 isValid() 返回false

警告: 1~99年就对应于它本身,不会偏移。第0年是非法的。

另请参阅:isValid() 和 QCalendar::dateFromParts()。


QDate::QDate()

构造一个空的日期,也是不可用的。

另请参阅:isNull() 和 isValid()。


QDate QDate::addDays(qint64 ndays) const

返回一个 ndays 天之后的新日期对象(负数意味着往前减日期)。

当当前日期或新日期是非法日期时,返回非法日期。

另请参阅:addMonths()、addYears() 和 daysTo()。


QDate QDate::addMonths(int nmonths) const

QDate QDate::addMonths(int nmonths, QCalendar cal) const

返回一个 nmonths 月之后的新日期对象(负数意味着往前减日期)。

如果传入 cal 参数,会使用日历系统使用,否则使用格里高利历。

注意: 如果新的日期超出年、月的合理范围,函数讲返回那个月中最接近的日期。

另请参阅:addDays() 和 addYears()。


QDate QDate::addYears(int nyears) const

QDate QDate::addYears(int nyears, QCalendar cal) const

返回一个 nyears 年之后的新日期对象(负数意味着往前减日期)。

如果传入 cal 参数,会使用日历系统使用,否则使用格里高利历。

注意: 如果新的日期超出年、月的合理范围,函数讲返回那个月中最接近的日期。

另请参阅:addDays() 和 addMonths()。


[static] QDate QDate::currentDate()

返回系统时钟所示的今天的日期对象。

另请参阅:QTime::currentTime() 和 QDateTime::currentDateTime()。


int QDate::day() const

int QDate::day(QCalendar cal) const

返回日期是当前月份的第几天。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历。非法日期则返回0。

一些日历系统中,返回值可能大于7。

另请参阅:year()、month() 和 dayOfWeek()。


int QDate::dayOfWeek() const

int QDate::dayOfWeek(QCalendar cal) const

返回日期是当前周的第几天(1=周一,7=周日)。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历。非法日期则返回0。

一些日历系统中,返回值可能大于7。

另请参阅:day()、dayOfYear() 和 Qt::DayOfWeek


int QDate::dayOfYear() const

int QDate::dayOfYear(QCalendar cal) const

返回日期是当年的第几天(第一天返回1)。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历。非法日期则返回0。

另请参阅:day() 和 dayOfWeek()。


int QDate::daysInMonth() const

int QDate::daysInMonth(QCalendar cal) const

返回日期对应的月份中总天数。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历 (返回值是 28~31)。非法日期则返回0。

另请参阅:day() 和 daysInYear()。


int QDate::daysInYear() const

int QDate::daysInYear(QCalendar cal) const

返回日期对应的一年中的总天数。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历 (返回值是 365 或 366)。非法日期则返回0。

另请参阅:day() 和 daysInMonth()。


qint64 QDate::daysTo(const QDate &d) const

返回两个日期相差的天数 (d 日期靠前则返回为负)。

如果比较的二者中有非法日期,返回0。

示例:

QDate d1(1995, 5, 17);  // May 17, 1995
QDate d2(1995, 5, 20);  // May 20, 1995
d1.daysTo(d2);          // returns 3
d2.daysTo(d1);          // returns -3

另请参阅:addDays()。


[static]QDate QDate::fromJulianDay(qint64 jd)

将jd表示的儒略日解析为日期并返回。

另请参阅:toJulianDay()。


[static]QDate QDate::fromString(const QString &string, Qt::DateFormat format = Qt::TextDate)

返回 string 表示的 QDate 对象,非法字符串不会被解析。

注意 Qt::TextDate:建议使用英文的简写月份名称(例如 "Jan")。尽管本地化的月份名称在 Qt 5 中也可使用,但它们会依赖于用户的区域设置。

注意: 对本地化的日期的支持,包括 Qt::SystemLocaleDateQt::SystemLocaleShortDateQt::SystemLocaleLongDateQt::LocaleDateQt::DefaultLocaleShortDateQt::DefaultLocaleLongDate,将在 Qt 6 被移除。使用 QLocale::toDate() 代替。

另请参阅:toString() 和 QLocale::toDate()。


[static]QDate QDate::fromString(const QString &string, const QString &format)

[static]QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)

返回 string 表示的 QDate 对象,非法字符串不会被解析。

如果传入 cal 参数,会使用此日历系统,否则使用格里高利历。下面的格式描述针对于格里高利历,其它日历可能不同。

日期格式的表示如下:

占位符输出格式
d无占位0的日期 (1 to 31)
dd有占位0的日期 (01 to 31)
ddd简写的一周七天名称(例如 'Mon' to 'Sun')。使用系统地域设置来格式化, 也就是 QLocale::system()
dddd长版的一周七天名称 (例如 'Monday' to 'Sunday')。使用系统地域设置来格式化, 也就是 QLocale::system()
M无占位0的月份 (1 to 12)
MM有占位0的月份 (01 to 12)
MMM缩写的月份名称 (例如 'Jan' to 'Dec')。使用系统地域设置来格式化, 也就是 QLocale::system()
MMMM长版的月份名称 (例如 'January' to 'December')。使用系统地域设置来格式化, 也就是 QLocale::system()
yy两位数年份 (00 to 99)
yyyy四位数年份。 如果是负数,加上符号是五个字符

注意: 不行此函数的其他版, 日期和月份名必须使用用户本地语言。只有用户语言是英语时,英文名称才适用。

所有其他字符将会被舍弃,单引号('')包裹的内容,无论是否包含格式占位符也会被舍弃。例如:

QDate date = QDate::fromString("1MM12car2003", "d'MM'MMcaryyyy");
// date is 1 December 2003

如果字符串不符合格式,一个将返回一个非法的 QDate。不需要前面补0的格式是贪婪的,这意味着他们会读取两位数,尽管数字大小超出日期合法范围,并且会占据给后续格式读取的数字位置。例如,下面的日期可以表示1月30日,但M格式会捕获两位数字,导致日期返回非法:

QDate date = QDate::fromString("130", "Md"); // invalid

年月日中,没有出现在格式中的,将会使用如下默认值:

字段默认值
Year1900
Month1
Day1

下面是默认值的示例:

QDate::fromString("1.30", "M.d");           // January 30 1900
QDate::fromString("20000110", "yyyyMMdd");  // January 10, 2000
QDate::fromString("20000110", "yyyyMd");    // January 10, 2000

注意: 如果使用本地化的日期表达, 请使用 QLocale::system().toDate(), 因为 QDate 将在 Qt 6使用英文表达 (C语言风格) 。

另请参阅:toString()、QDateTime::fromString()、QTime::fromString() 和 QLocale::toDate()。


void QDate::getDate(int *year, int *month, int *day) const

读取日期,储存到 *year, *month*day。指针可以是空指针。

如果日期非法,返回的是0。

注意: 在 Qt 5.7 之前, 这个函数不是常函数。

此函数在 Qt 4.5 中引入。

另请参阅:year(),month(),day(),isValid() 和 QCalendar::partsFromDate()。


[static]bool QDate::isLeapYear(int year)

判断是否是格里高利历的闰年,是则返回 true

另请参阅:QCalendar::isLeapYear()。


bool QDate::isNull() const

判断日期是否为空,日期为空则返回 true。 空日期是非法的。

注意: 行为与 isValid() 等价。

另请参阅:isValid()。


bool QDate::isValid() const

判断日期是否合法,合法返回 true

另请参阅:isNull() 和 QCalendar::isDateValid()。


[static]bool QDate::isValid(int year, int month, int day)

是上述方法的重载。

判断日期(以格里高利历解析)是否合法,合法返回 true

例如:

QDate::isValid(2002, 5, 17);  // true
QDate::isValid(2002, 2, 30);  // false (2月没有20日)
QDate::isValid(2004, 2, 29);  // true (是闰年)
QDate::isValid(2000, 2, 29);  // true (是闰年)
QDate::isValid(2006, 2, 29);  // false (不是闰年)
QDate::isValid(2100, 2, 29);  // false (不是闰年)
QDate::isValid(1202, 6, 6);   // true (即使这一年在格里高利历之前)

另请参阅:isNull(),setDate() 和 QCalendar::isDateValid()。


int QDate::month() const

int QDate::month(QCalendar cal) const

返回月份编号,第一个月返回1。

如果传入 cal 参数,会使用日历系统使用,否则使用格里高利历。

对于格里高利历,1月就是咱中文说的阳历一月。

对于非法日期返回0。注意有一些日历中,月份可能多于12个。

另请参阅:year() 和 day()。


bool QDate::setDate(int year, int month, int day)

设置对应的日期,使用的是格里高利历。 如果设置的日期合法,将返回 true,否则日期标记为非法并返回 false

此函数在 Qt 4.2 中引入。

另请参阅:isValid() 和 QCalendar::dateFromParts()。


bool QDate::setDate(int year, int month, int day, QCalendar cal)

设置对应的日期,使用的是cal对应的日历。如果设置的日期合法,将返回 true,否则日期标记为非法并返回 false

函数在 Qt 5.14 中引入。

另请参阅:isValid() 和 QCalendar::dateFromParts()。


qint64 QDate::toJulianDay() const

将日期转换为儒略日。

另请参阅:fromJulianDay()。


QString QDate::toString(Qt::DateFormat format = Qt::TextDate) const

这是一个重载函数,返回日期的字符串。 format 参数决定字符串格式。

如果 formatQt::TextDate,日期使用默认格式。日期月份将使用系统地域设置,也就是 QLocale::system()。一个例子是 "Sat May 20 1995"。

如果 formatQt::ISODate,字符串按照 ISO 8601 格式展开,格式形如 yyyy-MM-dd。例如2002-01-05

format 中的 Qt::SystemLocaleDateQt::SystemLocaleShortDateQt::SystemLocaleLongDate 将在 Qt 6 中删除。这些应当由 QLocale::system().toString(date, QLocale::ShortFormat)QLocale::system().toString(date, QLocale::LongFormat) 替代。

format 中的 Qt::LocaleDateQt::DefaultLocaleShortDateQt::DefaultLocaleLongDate 将在 Qt 6 中删除。这些应当由 QLocale().toString(date, QLocale::ShortFormat)QLocale().toString(date, QLocale::LongFormat) 替代。

如果 formatQt::RFC2822Date, 字符串会转换成 RFC 2822 兼容的格式。示例其一是 "20 May 1995"。

如果日期非法,返回空字符串。

警告: Qt::ISODate 格式只在0~9999年可用。

另请参阅:fromString() 和 QLocale::toString()。


int QDate::weekNumber(int *yearNumber = nullptr) const

返回 ISO 8601 周序号 (1 到 53)。对于非法日期返回0。

如果 yearNumber 不是 nullptr(默认参数), 年号返回值存于 *yearNumber

根据 ISO 8601, 格里高利历中,跨年的周属于天数更多的那年。 由于 ISO 8601 规定一周始于周一,周三在哪一年这周就属于哪一年。 大多数年有52周,但也有53周的年份。

注意: *yearNumber 不总是与 year() 相等。例如, 2000.1.1是1999年第52周, 2002.12.31是2003年第1周。

另请参阅:isValid()。


int QDate::year() const

int QDate::year(QCalendar cal) const

返回整数型的年份。

如果传入参数 cal , 它决定了使用的日历系统,默认是格里高利历。

如果日期不合法,返回0。在一些日历系统中,比第一年早的年份非法。

如果使用包含第0年的日历系统,在返回0时通过 isValid() 判断是否合法。这些日历正常的使用负年份,-1年的下一年是0年,再下一年是1年。

一些日历中,没有0年份但是有负数年份。例如格里高利历,公元前x年就是年份-x。

另请参阅:month(),day(),QCalendar::hasYearZero() 和 QCalendar::isProleptic()。


bool QDate::operator!=(const QDate &d) const

bool QDate::operator<(const QDate &d) const

bool QDate::operator<=(const QDate &d) const

bool QDate::operator==(const QDate &d) const

bool QDate::operator>(const QDate &d) const

bool QDate::operator>=(const QDate &d) const

对于日期A和B,大于意味着日期靠后,小于意味着日期靠前,相等就是同一天。

相关非成员函数

QDataStream &operator<<(QDataStream &out, const QDate &date)

向数据流写入日期

另请参阅:Serializing Qt Data Types


QDataStream &operator>>(QDataStream &in, QDate &date)

从数据流读出日期

另请参阅:Serializing Qt Data Types

QFile Class

QFile 类提供读写文件的接口。

属性方法
Header:#include
qmake:QT += core
Inherits:QFileDevice
Inherited By:QTemporaryFile

注意: 类中所有函数都是 可重入的

公共成员类型

类型方法
typedefDecoderFn

公共成员函数

类型方法
QFile(const QString &name, QObject *parent)
QFile(QObject *parent)
QFile(const QString &name)
QFile()
virtual~QFile()
boolcopy(const QString &newName)
boolexists() const
boollink(const QString &linkName)
boolmoveToTrash()
boolopen(FILE *fh, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle)
boolopen(int fd, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle)
boolremove()
boolrename(const QString &newName)
voidsetFileName(const QString &name)
QStringsymLinkTarget() const

重写公共函数

类型方法
virtual QStringfileName() const override
virtual boolopen(QIODevice::OpenMode mode) override
virtual QFileDevice::Permissionspermissions() const override
virtual boolresize(qint64 sz) override
virtual boolsetPermissions(QFileDevice::Permissions permissions) override
virtual qint64size() const override

静态公共成员

类型方法
boolcopy(const QString &fileName, const QString &newName)
QStringdecodeName(const QByteArray &localFileName)
QStringdecodeName(const char *localFileName)
QByteArrayencodeName(const QString &fileName)
boolexists(const QString &fileName)
boollink(const QString &fileName, const QString &linkName)
boolmoveToTrash(const QString &fileName, QString *pathInTrash = nullptr)
QFileDevice::Permissionspermissions(const QString &fileName)
boolremove(const QString &fileName)
boolrename(const QString &oldName, const QString &newName)
boolresize(const QString &fileName, qint64 sz)
boolsetPermissions(const QString &fileName, QFileDevice::Permissions permissions)
QStringsymLinkTarget(const QString &fileName)

详细描述

QFile 是用于读写文本及二进制的文件及资源的I/O设备。 一个QFile可以单独使用,或者更简单的,可以与 QTextStreamQDataStream 一同使用。

文件名通常在构造时传递,但也可以在随时使用 setFileName()设置。QFile 需要目录分隔符为 '/' 而不是依照操作系统。其他分隔符 (如 '\') 不受支持。

您可以通过 exists() 判断文件是否存在。(更多操作系统相关的操作在 QFileInfoQDir 中提供)

文件通过 open() 打开,通过 close() 关闭,通过 flush() 刷新。数据通常使用 QDataStream or QTextStream 读写,但您也可以使用 由 QIODevice 的继承函数 read(), readLine(), readAll(), write()。单字符的操作也可以使用 getChar(), putChar(), and ungetChar()。

size() 返回文件大小。您可以通过 pos() 获取当前文件位置,或通过 seek() 移动到新的位置(译者注:此句中的“位置”指文件内操作的字节位置)。当您读到文件结尾, atEnd() 返回 true

直接读文件

如下例子逐行地直接读取文本文件:

    QFile file("in.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    while (!file.atEnd()) {
        QByteArray line = file.readLine();
        process_line(line);
    }

QIODevice::Text flag传递给 open() ,其告诉Qt将Windows风格的换行符 ("\r\n") 转换为 C++风格的换行符("\n")。默认情况下,QFile 假设为二进制模式读取,不做字节转换。

通过流来读文件

如下例子逐行地通过 QTextStream 读取文本文件:

    QFile file("in.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine();
        process_line(line);
    }

QTextStream 会特意把8位文件中字节数据转换为QString中16位UTF-16字符。默认情况下,其假设用户使用系统默认编码(例如unix平台上是UTF-8;详情参看 QTextCodec::codecForLocale() )。编码可以通过 QTextStream::setCodec() 改变。

要写入文本,您可以使用左移运算符运算符 operator<<(),在 QTextStream 中,其重载用于讲右侧内容追加的左侧,示例如下:

    QFile file("out.txt");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;

    QTextStream out(&file);
    out << "The magic number is: " << 49 << "\n";

QDataStream 和上文很相似,详情请见相当应类的文档。

当你使用 QFile, QFileInfo 以及 QDir 来访问系统中文件,你可以使用Unicode文件名。在Unix平台,文件名会转换为8位编码。如果您想使用C++标准API (<cstdio><iostream>) 或平台相关API来访问文件而不是使用 QFile,你可以使用 encodeName() 和 decodeName() 来在Unicode文件名和8位文件名间转换。

在Unix平台,有一些特殊的系统文件 (例如 /proc 下的文件) ,对于这些文件,size() 会返回0,但你依然可以读取更多数据;这些数据在你调用 read() 时即时产生。在这种情况下,您便不能使用 atEnd() 来判断是否已经没有更多数据。(因为 atEnd() 通过文件大小是否到达结尾)。然而您可以通过连续调用 readAll(), read() 或 readLine() 指导没有数据来替代此功能。下面的例子使用 QTextStream 逐行读取/proc/modules

    QFile file("/proc/modules");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    QString line = in.readLine();
    while (!line.isNull()) {
        process_line(line);
        line = in.readLine();
    }

信号

不像其他 QIODevice 的实现,例如 QTcpSocket,QFile 不会发出 aboutToClose(), bytesWritten(), 及 readyRead() 这些信号。这个实现细节意味着 QFile 不适用于读写某些特定类型的文件,比如Unix上的设备文件。

平台相关信息

文件权限和Unix和Windows上的处理并不相同。在Unix平台上,一个非 可写入 的目录,文件无法创建。但对于Windows并不一定如此,例如 'My Documents' (我的文档)目录通常不可写入,但是在其中依然可以创建文件。

Qt对于文件权限的理解有局限,尤其对于 QFile::setPermissions() 有影响。在Windows上,仅当没有任何 Write* flags被设置时,Qt 会设置旧版的只读 flag。Qt不会操作访问过滤表(access control lists , ACLs)这是的此函数在NTFS卷上基本上没什么用。对于VFAT格式的U盘,倒是有可能可用。POSIX 的 ACLs 也不会被修改。

另请参见 QTextStream, QDataStream, QFileInfo, QDir, 以及 The Qt Resource System

成员类型文档

typedef QFile::DecoderFn

这个类型定义了一个如下形式的函数的指针:

QString myDecoderFunc(const QByteArray &localFileName);

另请参见 setDecodingFunction().

成员函数文档

QFile::QFile(const QString &name, QObject *parent)

构造基于给定的父对象 parent 、文件名 name 指定的QFile对象。


QFile::QFile(QObject *parent)

构造基于给定的父对象 parent 的QFile对象。


QFile::QFile(const QString &name)

构造文件名 name 指定的QFile对象。


QFile::QFile()

构造一个QFile对象。


[virtual]QFile::~QFile()

销毁此QFile对象,如需要会自动关闭文件。


bool QFile::copy(const QString &newName)

将当前 fileName() 指定的文件复制为文件名 newName 指定的文件。如果成功,返回 true ;否则返回 false

注意如果 newName 文件名的文件已存在,函数不会覆盖,直接返回 false

源文件会在复制前关闭。

另请参见 setFileName().


[static]bool QFile::copy(const QString &fileName, const QString &newName)

这是一个重载函数。

将文件 fileName 复制为文件名 newName。如果成功,返回 true ;否则返回 false

注意如果 newName 文件名的文件已存在,函数不会覆盖,直接返回 false

另请参见 rename().


[static]QString QFile::decodeName(const QByteArray &localFileName)

QFile::encodeName() 操作恰恰相反。返回 localFileName 的Unicode形式。

另请参见 encodeName().


[static]QString QFile::decodeName(const char *localFileName)

这是一个重载函数。返回 localFileName 的Unicode形式。

详情参见 encodeName() 。


[static]QByteArray QFile::encodeName(const QString &fileName)

基于用户区域设置,将 fileName 转换为本地的8为表示。这对于用户选择的文件名足够使用。硬编码到程序中的文件名应当只使用7位ASCII字符。

另请参见 decodeName().


[static]bool QFile::exists(const QString &fileName)

如果 fileName 对应的文件存在,返回 true 否则返回 false

注意: 如果 fileName 是指向不存在文件的符号链接,返回 false


bool QFile::exists() const

这是一个重载函数。

如果 fileName() 对应的文件存在,返回 true 否则返回 false

另请参见 fileName() and setFileName().


[override virtual]QString QFile::fileName() const

重写函数: QFileDevice::fileName() const.

返回 setFileName() 或构造函数设置的文件名。

另请参见 setFileName() and QFileInfo::fileName().


bool QFile::link(const QString &linkName)

创建一个名为 linkName 的、指向 fileName() 文件的链接。链接的形式取决于底层文件系统(Windows上的快捷方式或Linux下的符号链接symlink)。如果成功,返回 true ;返回 false

此函数不会覆盖文件系统上已经存在的链接;如果已存在,link() 将返回 false 并设置 error()RenameError

注意: 对于Windows平台,一个合法的链接名称必须包含 .lnk 后缀名。

另请参见 setFileName().


[static]bool QFile::link(const QString &fileName, const QString &linkName)

这是一个重载函数。

创建一个名为 linkName 的、指向 fileName 文件的链接。链接的形式取决于底层文件系统(Windows上的快捷方式或Linux下的符号链接symlink)。如果成功,返回 true ;否则返回 false

另请参见 link().


bool QFile::moveToTrash()

fileName() 文件移入回收站。如果成功返回 true ,并将 fileName() 设置为回收站中对应文件的路径;否则返回 false

注意: 在API不能返回回收站中文件的路径的操作系统中,一旦文件被移动 fileName() 会被设置为空字符串。在没有回收站的操作系统,此函数总返回 false

此函数引入自: Qt 5.15.


[static]bool QFile::moveToTrash(const QString &fileName, QString *pathInTrash = nullptr)

这是一个重载函数。

fileName 文件移入回收站。如果成功返回 true ,并将 *pathInTrash 设置为回收站中对应文件的路径字符串的指针;否则返回 false

注意: 在API不能返回回收站中文件的路径的操作系统中,一旦文件被移动 *pathInTrash 会被设置为空字符串。在没有回收站的操作系统,此函数总返回 false

此函数引入自: Qt 5.15.


[override virtual]bool QFile::open(QIODevice::OpenMode mode)

重写函数: QIODevice::open(QIODevice::OpenMode mode)。

使用 OpenMode mode 模式打开文件,如果成功,返回 true ;否则返回 false

模式 mode 必须是 QIODevice::ReadOnly, QIODevice::WriteOnly, 或 QIODevice::ReadWrite。也可以有附加flags,例如 QIODevice::TextQIODevice::Unbuffered

注意:WriteOnlyReadWrite 模式,如果相关文件不存在,此函数会尝试在打开前新建。

另请参见 QIODevice::OpenMode and setFileName().


bool QFile::open(FILE *fh, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle)

这是一个重载函数。

使用给出的模式 mode 打开已有的文件句柄 fhhandleFlags 可能会被用于指定附加选项。如果成功,返回 true ;否则返回 false

例如:

#include <stdio.h>

void printError(const char* msg)
{
    QFile file;
    file.open(stderr, QIODevice::WriteOnly);
    file.write(msg, qstrlen(msg));        // 写入 stderr
    file.close();
}

当一个 QFile 通过此函数被被打开,close() 的行为由 AutoCloseHandle flag决定。如果指定了 AutoCloseHandle ,且此函数执行成功,那么 close() 会关闭传入的句柄。否则,close() 不会关闭文件,只会刷新数据(flush)。

警告:

  1. 如果 fh 并非指向常规文件,例如 stdin, stdout, 或 stderr,你可能不能够使用 seek(),且size() 返回0。详见 QIODevice::isSequential()。
  2. 由于使用此函数打开的文件没有指定文件名,你不能通过 QFileInfo 读取相关信息。

Windows平台的注意事项

当访问文件或其他随机存取设备时,fh 必须以二进制模式打开(也就是 fopen() 的模式串必须包含'b')。Qt 会转换行末字节如果您指定 QIODevice::Textmode。顺序读取设备,例如标准输入输出,不受此限制影响。

您需要启用控制台应用支持,才能在控制台使用标准输入输出。要启用,可以在项目文件中加入:

CONFIG += console

另请参见 close().


bool QFile::open(int fd, QIODevice::OpenMode mode, QFileDevice::FileHandleFlags handleFlags = DontCloseHandle)

这是一个重载函数。

使用给出的模式 mode 打开已有的文件描述符 fhhandleFlags 可能会被用于指定附加选项。如果成功,返回 true ;否则返回 false

当一个 QFile 通过此函数被被打开,close() 的行为由 AutoCloseHandle flag决定。如果指定了 AutoCloseHandle ,且此函数执行成功,那么 close() 会关闭传入的句柄。否则,close() 不会关闭文件,只会刷新数据(flush)。

通过此函数打开的文件会被自动设置为 raw 模式;这意味着文件I/O函数会很慢。如果您遇到了性能问题,可以尝试其他 open() 函数。

警告:

  1. 如果 fd 不是一个常规文件,例如 0 (stdin), 1 (stdout), 或 2 (stderr),你可能不能够使用 seek(),且size() 返回0。详见 QIODevice::isSequential()。

  2. 由于使用此函数打开的文件没有指定文件名,你不能通过 QFileInfo 读取相关信息。

另请参见 close().


[override virtual]QFileDevice::Permissions QFile::permissions() const

重写函数: QFileDevice::permissions() const.

另请参见 setPermissions().


[static]QFileDevice::Permissions QFile::permissions(const QString &fileName)

这是一个重载函数。

返回 fileName 文件经 OR(位或)后的权限 QFile::Permission 组合。


bool QFile::remove()

删除文件名 fileName() 的文件。

如果成功,返回 true ;否则返回 false

文件会在删除前关闭。

另请参见 setFileName().


[static]bool QFile::remove(const QString &fileName)

这是一个重载函数。

删除文件名 fileName 的文件。

如果成功,返回 true ;否则返回 false

另请参见 remove().


bool QFile::rename(const QString &newName)

把文件 fileName() 重命名为 newName。如果成功,返回 true ;否则返回 false

注意如果 newName 文件名的文件已存在,函数不会覆盖,直接返回 false

文件在重命名前关闭。

如果直接重命名失败,Qt会尝试拷贝数据到 newName 新文件并删除旧文件来实现重命名。如果拷贝或删除失败,Qt会撤回新文件创建,返回原先状态。

另请参见 setFileName().


[static]bool QFile::rename(const QString &oldName, const QString &newName)

这是一个重载函数。

把文件 oldName 重命名为 newName。如果成功,返回 true ;否则返回 false

注意如果 newName 文件名的文件已存在,函数不会覆盖,直接返回 false

另请参见 rename().


[override virtual]bool QFile::resize(qint64 sz)

重写函数: QFileDevice::resize(qint64 sz).


[static]bool QFile::resize(const QString &fileName, qint64 sz)

这是一个重载函数。

这是文件名 fileName 文件的大小为 sz 字节。如果修改大小成功返回 true,否则返回 false。如果 sz 比当前文件大小大,后面的数据会填充0;如果 sz 比当前文件大小小,会裁剪文件数据。

警告: 如果文件不存在,调用会失败。

另请参见 resize().


void QFile::setFileName(const QString &name)

设置文件名 name。名称可以不包含目录,包含相对目录或绝对目录。

请不要在文件已经打开后调用此函数。

如果文件名不包含路径,或者是相对路径,路径会基于应用程序调用 open() 时的当前路径。

例如:

QFile file;
QDir::setCurrent("/tmp");
file.setFileName("readme.txt");
QDir::setCurrent("/home");
file.open(QIODevice::ReadOnly);      // 打开Unix下文件 "/home/readme.txt"

注意Qt中目录分隔符统一使用"/".

另请参见 fileName(), QFileInfo, and QDir.


[override virtual]bool QFile::setPermissions(QFileDevice::Permissions permissions)

重写函数: QFileDevice::setPermissions(QFileDevice::Permissions permissions).

为文件设置 permissions 权限。如果成功返回 true ,如果权限不能修改返回 false

警告: 此函数不会操作修改 ACLs,这会限制函数功能。

另请参见 permissions() and setFileName().


[static]bool QFile::setPermissions(const QString &fileName, QFileDevice::Permissions permissions)

这是一个重载函数。

为文件名 fileName 的文件设置 permissions 权限。


[override virtual]qint64 QFile::size() const

重写函数: QFileDevice::size() const.


[static]QString QFile::symLinkTarget(const QString &fileName)

返回符号链接(Unix上的symlink或Windows上快捷方式)fileName 指向的文件或目录的绝对路径。如果 fileName 不是一个符号链接,返回空字符串。

名称可能并不是一个存在的文件,只是一个字符串路径。QFile::exists() 可以用来判断是否存在。

此函数引入自: Qt 4.2.


QString QFile::symLinkTarget() const

这是一个重载函数。

返回QFile对象对应的符号链接(Unix上的symlink或Windows上快捷方式)指向的文件或目录的绝对路径。如果 fileName 不是一个符号链接,返回空字符串。

名称可能并不是一个存在的文件,只是一个字符串路径。QFile::exists() 可以用来判断是否存在。

此函数引入自: Qt 4.2.

另请参见 fileName() and setFileName().

QFileInfo 类

QFileInfo 类用于系统无关的文件信息。更多内容...

属性方法
头文件:#include <QFileInfo>
qmake:QT += core

注意 此类中所有函数均 可重入

公共成员函数

返回类型函数名
QFileInfo(const QFileInfo &fileinfo)
QFileInfo(const QDir &dir, const QString &file)
QFileInfo(const QFile &file)
QFileInfo(const QString &file)
QFileInfo()
QFileInfo &operator=(QFileInfo &&other)
QFileInfo &operator=(const QFileInfo &fileinfo)
~QFileInfo()
QDirabsoluteDir() const
QStringabsoluteFilePath() const
QStringabsolutePath() const
QStringbaseName() const
QDateTimebirthTime() const
QStringbundleName() const
boolcaching() const
QStringcanonicalFilePath() const
QStringcanonicalPath() const
QStringcompleteBaseName() const
QStringcompleteSuffix() const
QDirdir() const
boolexists() const
QStringfileName() const
QStringfilePath() const
QDateTimefileTime(QFile::FileTime time) const
QStringgroup() const
uintgroupId() const
boolisAbsolute() const
boolisBundle() const
boolisDir() const
boolisExecutable() const
boolisFile() const
boolisHidden() const
boolisJunction() const
boolisNativePath() const
boolisReadable() const
boolisRelative() const
boolisRoot() const
boolisShortcut() const
boolisSymLink() const
boolisSymbolicLink() const
boolisWritable() const
QDateTimelastModified() const
QDateTimelastRead() const
boolmakeAbsolute()
QDateTimemetadataChangeTime() const
QStringowner() const
uintownerId() const
QStringpath() const
boolpermission(QFile::Permissions permissions) const
QFile::Permissionspermissions() const
voidrefresh()
voidsetCaching(bool enable)
voidsetFile(const QString &file)
voidsetFile(const QFile &file)
voidsetFile(const QDir &dir, const QString &file)
qint64size() const
QStringsuffix() const
voidswap(QFileInfo &other)
QStringsymLinkTarget() const
booloperator!=(const QFileInfo &fileinfo) const
booloperator==(const QFileInfo &fileinfo) const

静态公共成员函数

返回类型函数名
boolexists(const QString &file)

相关非成员

返回类型函数名
typedefQFileInfoList

详细描述

QFileInfo 可以获取任一文件的名字、路径、访问权限、是否是文件夹及是否是符号链接等信息,也可以获取文件的大小、上次修改时间、上次读取时间,还可以获取 Qt 资源文件 的信息。

QFileInfo 可以表示相对路径也可以表示绝对路径。绝对路径以 “/” (windows 上以驱动符号)开头(例如 "/tmp/quartz"),相对路径以目录名或文件名开头,相对于当前工作目录(例如 "src/fatlib")。可以用 isRelative() 检查一个 QFileInfo 表示的是相对路径还是绝对路径。可以用 makeAbsolute() 将相对路径转为绝对路径。

QFileInfo 可以在构造函数中或稍后在 setFile() 设置文件,可以用 exists() 查看文件是否存在,可以用 size() 获取文件大小。

文件类型可以用 isFile()、isDir() 和 isSymLink() 获取。symLinkTarget() 函数提供了符号链接指向的文件名。

在 Unix 系统(包括 macOS 和 iOS),此类的属性的 getter 函数(例如获取时间或大小)返回的都是目标文件的值,而不是符号链接的(因为Unix透明地处理符号链接)。使用 QFile 打开符号链接实际上是打开链接的目标。举例如下:

#ifdef Q_OS_UNIX

QFileInfo info1("/home/bob/bin/untabify");
info1.isSymLink();          // returns true
info1.absoluteFilePath();   // returns "/home/bob/bin/untabify"
info1.size();               // returns 56201
info1.symLinkTarget();      // returns "/opt/pretty++/bin/untabify"

QFileInfo info2(info1.symLinkTarget());
info2.isSymLink();          // returns false
info2.absoluteFilePath();   // returns "/opt/pretty++/bin/untabify"
info2.size();               // returns 56201

#endif

在Windows上,快捷方式(“.lnk”文件)当前被视为符号链接。 和Unix系统一样,属性的 getter 返回目标文件的大小,而不是.lnk文件本身。 此行为已被弃用,并且可能会在Qt的未来版本中删除,此后,.lnk 文件将被视为常规文件。

#ifdef Q_OS_WIN

QFileInfo info1("C:\\Documents and Settings\\Bob\\untabify.lnk");
info1.isSymLink();          // returns true
info1.absoluteFilePath();   // returns "C:/Documents and Settings/Bob/untabify.lnk"
info1.size();               // returns 743
info1.symLinkTarget();      // returns "C:/Pretty++/untabify"

QFileInfo info2(info1.symLinkTarget());
info2.isSymLink();          // returns false
info2.absoluteFilePath();   // returns "C:/Pretty++/untabify"
info2.size();               // returns 63942

#endif

Elements of the file's name can be extracted with path() and fileName(). The fileName()'s parts can be extracted with baseName(), suffix() or completeSuffix(). QFileInfo objects to directories created by Qt classes will not have a trailing file separator. If you wish to use trailing separators in your own file info objects, just append one to the file name given to the constructors or setFile().

涉及文件日期的函数: birthTime() lastModified() lastRead() fileTime()

涉及文件访问权限的函数: isReadable() isWritable() isExecutable()

涉及文件所有权的函数: owner() ownerId() group() groupId()

同时查验文件权限及所有权: permission()

注意 在NTFS文件系统上,出于性能原因,默认情况下禁用所有权和权限检查。 要启用它,请包含以下行:

extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;

然后,通过将qt_ntfs_permission_lookup递增和递减 1 来打开和关闭权限检查。

qt_ntfs_permission_lookup++; // 打开检查
qt_ntfs_permission_lookup--; // 再次关闭

性能问题

Some of QFileInfo's functions query the file system, but for performance reasons, some functions only operate on the file name itself. For example: To return the absolute path of a relative file name, absolutePath() has to query the file system. The path() function, however, can work on the file name directly, and so it is faster.

注意 To speed up performance, QFileInfo caches information about the file.

Because files can be changed by other users or programs, or even by other parts of the same program, there is a function that refreshes the file information: refresh(). If you want to switch off a QFileInfo's caching and force it to access the file system every time you request information from it call setCaching(false).

另请参阅 QDir and QFile.

成员函数文档

QFileInfo::QFileInfo(const QFileInfo &fileinfo)

复制一个新的 QFileInfo。

QFileInfo::QFileInfo(const QDir &dir, const QString &file)

构造一个新的 QFileInfo,表示指定 dir 目录中的 file 文件信息。

如果 dir 具有相对路径,则 QFileInfo 也将具有相对路径。

如果 file 是绝对路径,则 dir 指定的目录将被忽略。

另请参阅 isRelative()

QFileInfo::QFileInfo(const QFile &file)

构造一个新的 QFileInfo,表示指定的 file 文件信息。

如果文件具有相对路径,则 QFileInfo 也将具有相对路径。

另请参阅 isRelative()

QFileInfo::QFileInfo(const QString &file)

构造一个新的 QFileInfo,表示指定的 file 文件信息。file 可以包含绝对或相对路径。

另请参阅 setFile(),isRelative(),QDir::setCurrent() 和 QDir::isRelativePath()

QFileInfo::QFileInfo()

构造一个空的 QFileInfo 对象。

注意,空的 QFileInfo 对象不包含文件引用。

另请参阅 setFile()

QFileInfo &QFileInfo::operator=(QFileInfo &&other)

移动构造函数。

该函数在 Qt 5.2 引入

QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)

赋值构造函数。

QFileInfo::~QFileInfo()

析构函数。

QDir QFileInfo::absoluteDir() const

QDir 对象的形式返回文件的绝对路径。

另请参阅 dir(),filePath(),fileName() 和 isRelative()

QString QFileInfo::absoluteFilePath() const

返回包含文件名的绝对路径。

绝对路径名由完整路径和文件名组成。 在Unix上,它将始终以根目录“ /”开头。 在Windows上,它将始终以“ D:/”开头,其中D是驱动器号,但未映射到驱动器号的网络共享除外,在这种情况下,路径将以“ // sharename /”开头。 QFileInfo 将大写驱动器号。

Returns an absolute path including the file name.

The absolute path name consists of the full path and the file name. On Unix this will always begin with the root, '/', directory. On Windows this will always begin 'D:/' where D is a drive letter, except for network shares that are not mapped to a drive letter, in which case the path will begin '//sharename/'. QFileInfo will uppercase drive letters. Note that QDir does not do this. The code snippet below shows this.

    QFileInfo fi("c:/temp/foo"); => fi.absoluteFilePath() => "C:/temp/foo"

This function returns the same as filePath(), unless isRelative() is true. In contrast to canonicalFilePath(), symbolic links or redundant "." or ".." elements are not necessarily removed.

警告 If filePath() is empty the behavior of this function is undefined.

另请参阅 filePath(), canonicalFilePath(), and isRelative().

QString QFileInfo::absolutePath() const

Returns a file's path absolute path. This doesn't include the file name.

On Unix the absolute path will always begin with the root, '/', directory. On Windows this will always begin 'D:/' where D is a drive letter, except for network shares that are not mapped to a drive letter, in which case the path will begin '//sharename/'.

In contrast to canonicalPath() symbolic links or redundant "." or ".." elements are not necessarily removed.

警告 If filePath() is empty the behavior of this function is undefined.

另请参阅 absoluteFilePath(), path(), canonicalPath(), fileName(), and isRelative().

QString QFileInfo::baseName() const

Returns the base name of the file without the path.

The base name consists of all characters in the file up to (but not including) the first '.' character.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.baseName();  // base = "archive"

The base name of a file is computed equally on all platforms, independent of file naming conventions (e.g., ".bashrc" on Unix has an empty base name, and the suffix is "bashrc").

另请参阅 fileName(), suffix(), completeSuffix(), and completeBaseName()

QDateTime QFileInfo::birthTime() const

Returns the date and time when the file was created / born.

If the file birth time is not available, this function returns an invalid QDateTime

If the file is a symlink, the time of the target file is returned (not the symlink).

This function was introduced in Qt 5.10.

另请参阅 lastModified(), lastRead(), and metadataChangeTime()

QString QFileInfo::bundleName() const

Returns the name of the bundle.

On macOS and iOS this returns the proper localized name for a bundle if the path isBundle(). On all other platforms an empty QString is returned.

Example:

QFileInfo fi("/Applications/Safari.app");
QString bundle = fi.bundleName();                // name = "Safari"

This function was introduced in Qt 4.3.

另请参阅 isBundle(), filePath(), baseName(), and suffix().

bool QFileInfo::caching() const

Returns true if caching is enabled; otherwise returns false.

另请参阅 setCaching() and refresh().

QString QFileInfo::canonicalFilePath() const

Returns the canonical path including the file name, i.e. an absolute path without symbolic links or redundant "." or ".." elements.

If the file does not exist, canonicalFilePath() returns an empty string.

另请参阅 filePath(), absoluteFilePath(), and dir().

QString QFileInfo::canonicalPath() const

Returns the file's path canonical path (excluding the file name), i.e. an absolute path without symbolic links or redundant "." or ".." elements.

If the file does not exist, canonicalPath() returns an empty string.

另请参阅 path() and absolutePath().

QString QFileInfo::completeBaseName() const

Returns the complete base name of the file without the path.

The complete base name consists of all characters in the file up to (but not including) the last '.' character.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
QString base = fi.completeBaseName();  // base = "archive.tar"

另请参阅 fileName(), suffix(), completeSuffix(), and baseName().

QString QFileInfo::completeSuffix() const

Returns the complete suffix (extension) of the file.

The complete suffix consists of all characters in the file after (but not including) the first '.'.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
QString ext = fi.completeSuffix();  // ext = "tar.gz"

另请参阅 fileName(), suffix(), baseName(), and completeBaseName().

QDir QFileInfo::dir() const

Returns the path of the object's parent directory as a QDir object.

注意 The QDir returned always corresponds to the object's parent directory, even if the QFileInfo represents a directory.

For each of the following, dir() returns the QDir "~/examples/191697".

    QFileInfo fileInfo1("~/examples/191697/.");
    QFileInfo fileInfo2("~/examples/191697/..");
    QFileInfo fileInfo3("~/examples/191697/main.cpp");

For each of the following, dir() returns the QDir ".".

    QFileInfo fileInfo4(".");
    QFileInfo fileInfo5("..");
    QFileInfo fileInfo6("main.cpp");

另请参阅 absolutePath(), filePath(), fileName(), isRelative(), and absoluteDir().

bool QFileInfo::exists() const

Returns true if the file exists; otherwise returns false.

注意 If the file is a symlink that points to a non-existing file, false is returned.

[static]bool QFileInfo::exists(const QString &file)

Returns true if the file exists; otherwise returns false.

注意 If file is a symlink that points to a non-existing file, false is returned.

注意 Using this function is faster than using QFileInfo(file).exists() for file system access.

This function was introduced in Qt 5.2.

QString QFileInfo::fileName() const

Returns the name of the file, excluding the path.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
QString name = fi.fileName();                // name = "archive.tar.gz"

Note that, if this QFileInfo object is given a path ending in a slash, the name of the file is considered empty.

另请参阅 isRelative(), filePath(), baseName(), and suffix().

QString QFileInfo::filePath() const

Returns the file name, including the path (which may be absolute or relative).

另请参阅 absoluteFilePath(), canonicalFilePath(), and isRelative().

QDateTime QFileInfo::fileTime(QFile::FileTime time) const

Returns the file time specified by time. If the time cannot be determined, an invalid date time is returned.

If the file is a symlink, the time of the target file is returned (not the symlink).

This function was introduced in Qt 5.10.

另请参阅 QFile::FileTime and QDateTime::isValid().

QString QFileInfo::group() const

Returns the group of the file. On Windows, on systems where files do not have groups, or if an error occurs, an empty string is returned.

This function can be time consuming under Unix (in the order of milliseconds).

If the file is a symlink, this function returns the owning group of the target (not the symlink).

另请参阅 groupId(), owner(), and ownerId().

uint QFileInfo::groupId() const

Returns the id of the group the file belongs to.

On Windows and on systems where files do not have groups this function always returns (uint) -2.

If the file is a symlink, this function returns the id of the group owning the target (not the symlink).

另请参阅 group(), owner(), and ownerId().

bool QFileInfo::isAbsolute() const

Returns true if the file path name is absolute, otherwise returns false if the path is relative.

另请参阅 isRelative().

bool QFileInfo::isBundle() const

Returns true if this object points to a bundle or to a symbolic link to a bundle on macOS and iOS; otherwise returns false.

If the file is a symlink, this function returns true if the target is a bundle (not the symlink).

This function was introduced in Qt 4.3.

另请参阅 isDir(), isSymLink(), and isFile().

bool QFileInfo::isDir() const

Returns true if this object points to a directory or to a symbolic link to a directory; otherwise returns false.

If the file is a symlink, this function returns true if the target is a directory (not the symlink).

另请参阅 isFile(), isSymLink(), and isBundle().

bool QFileInfo::isExecutable() const

Returns true if the file is executable; otherwise returns false.

If the file is a symlink, this function returns true if the target is executable (not the symlink).

另请参阅 isReadable(), isWritable(), and permission().

bool QFileInfo::isFile() const

Returns true if this object points to a file or to a symbolic link to a file. Returns false if the object points to something which isn't a file, such as a directory.

If the file is a symlink, this function returns true if the target is a regular file (not the symlink).

另请参阅 isDir(), isSymLink(), and isBundle().

bool QFileInfo::isHidden() const

Returns true if this is a hidden file; otherwise returns false.

注意 This function returns true for the special entries "." and ".." on Unix, even though QDir::entryList threats them as shown. And note that, since this function inspects the file name, on Unix it will inspect the name of the symlink, if this file is a symlink, not the target's name.

On Windows, this function returns true if the target file is hidden (not the symlink).

bool QFileInfo::isJunction() const

Returns true if the object points to a junction; otherwise returns false.

Junctions only exist on Windows' NTFS file system, and are typically created by the mklink command. They can be thought of as symlinks for directories, and can only be created for absolute paths on the local volume.

This function was introduced in Qt 5.15.

bool QFileInfo::isNativePath() const

Returns true if the file path can be used directly with native APIs. Returns false if the file is otherwise supported by a virtual file system inside Qt, such as the Qt Resource System.

注意 Native paths may still require conversion of path separators and character encoding, depending on platform and input requirements of the native API.

This function was introduced in Qt 5.0.

另请参阅 QDir::toNativeSeparators(), QFile::encodeName(), filePath(), absoluteFilePath(), and canonicalFilePath().

bool QFileInfo::isReadable() const

Returns true if the user can read the file; otherwise returns false.

If the file is a symlink, this function returns true if the target is readable (not the symlink).

注意 If the NTFS permissions check has not been enabled, the result on Windows will merely reflect whether the file exists.

另请参阅 isWritable(), isExecutable(), and permission().

bool QFileInfo::isRelative() const

Returns true if the file path name is relative, otherwise returns false if the path is absolute (e.g. under Unix a path is absolute if it begins with a "/").

另请参阅 isAbsolute().

bool QFileInfo::isRoot() const

Returns true if the object points to a directory or to a symbolic link to a directory, and that directory is the root directory; otherwise returns false.

bool QFileInfo::isShortcut() const

Returns true if this object points to a shortcut; otherwise returns false.

Shortcuts only exist on Windows and are typically .lnk files. For instance, true will be returned for shortcuts (*.lnk files) on Windows, but false will be returned on Unix (including macOS and iOS).

The shortcut (.lnk) files are treated as regular files. Opening those will open the .lnk file itself. In order to open the file a shortcut references to, it must uses symLinkTarget() on a shortcut.

注意 Even if a shortcut (broken shortcut) points to a non existing file, isShortcut() returns true.

另请参阅 isFile(), isDir(), isSymbolicLink(), and symLinkTarget().

bool QFileInfo::isSymLink() const

Returns true if this object points to a symbolic link or shortcut; otherwise returns false.

Symbolic links exist on Unix (including macOS and iOS) and Windows and are typically created by the ln -s or mklink commands, respectively. Opening a symbolic link effectively opens the link's target.

In addition, true will be returned for shortcuts (*.lnk files) on Windows. This behavior is deprecated and will likely change in a future version of Qt. Opening those will open the .lnk file itself.

Example:

QFileInfo info(fileName);
if (info.isSymLink())
    fileName = info.symLinkTarget();

注意 If the symlink points to a non existing file, exists() returns false.

另请参阅 isFile(), isDir(), and symLinkTarget().

bool QFileInfo::isSymbolicLink() const

Returns true if this object points to a symbolic link; otherwise returns false.

Symbolic links exist on Unix (including macOS and iOS) and Windows (NTFS-symlink) and are typically created by the ln -s or mklink commands, respectively.

Unix handles symlinks transparently. Opening a symbolic link effectively opens the link's target.

In contrast to isSymLink(), false will be returned for shortcuts (*.lnk files) on Windows. Use QFileInfo::isShortcut() instead.

注意 If the symlink points to a non existing file, exists() returns false.

另请参阅 isFile(), isDir(), isShortcut(), and symLinkTarget().

bool QFileInfo::isWritable() const

Returns true if the user can write to the file; otherwise returns false.

If the file is a symlink, this function returns true if the target is writeable (not the symlink).

注意 If the NTFS permissions check has not been enabled, the result on Windows will merely reflect whether the file is marked as Read Only.

另请参阅 isReadable(), isExecutable(), and permission().

QDateTime QFileInfo::lastModified() const

Returns the date and local time when the file was last modified.

If the file is a symlink, the time of the target file is returned (not the symlink).

另请参阅 birthTime(), lastRead(), metadataChangeTime(), and fileTime().

QDateTime QFileInfo::lastRead() const

Returns the date and local time when the file was last read (accessed).

On platforms where this information is not available, returns the same as lastModified().

If the file is a symlink, the time of the target file is returned (not the symlink).

另请参阅 birthTime(), lastModified(), metadataChangeTime(), and fileTime().

bool QFileInfo::makeAbsolute()

Converts the file's path to an absolute path if it is not already in that form. Returns true to indicate that the path was converted; otherwise returns false to indicate that the path was already absolute.

另请参阅 filePath() and isRelative().

QDateTime QFileInfo::metadataChangeTime() const

Returns the date and time when the file metadata was changed. A metadata change occurs when the file is created, but it also occurs whenever the user writes or sets inode information (for example, changing the file permissions).

If the file is a symlink, the time of the target file is returned (not the symlink).

This function was introduced in Qt 5.10.

另请参阅 lastModified() and lastRead().

QString QFileInfo::owner() const

Returns the owner of the file. On systems where files do not have owners, or if an error occurs, an empty string is returned.

This function can be time consuming under Unix (in the order of milliseconds). On Windows, it will return an empty string unless the NTFS permissions check has been enabled.

If the file is a symlink, this function returns the owner of the target (not the symlink).

另请参阅 ownerId(), group(), and groupId().

uint QFileInfo::ownerId() const

Returns the id of the owner of the file.

On Windows and on systems where files do not have owners this function returns ((uint) -2).

If the file is a symlink, this function returns the id of the owner of the target (not the symlink).

另请参阅 owner(), group(), and groupId().

QString QFileInfo::path() const

Returns the file's path. This doesn't include the file name.

Note that, if this QFileInfo object is given a path ending in a slash, the name of the file is considered empty and this function will return the entire path.

另请参阅 filePath(), absolutePath(), canonicalPath(), dir(), fileName(), and isRelative().

bool QFileInfo::permission(QFile::Permissions permissions) const

Tests for file permissions. The permissions argument can be several flags of type QFile::Permissions OR-ed together to check for permission combinations.

On systems where files do not have permissions this function always returns true.

注意 The result might be inaccurate on Windows if the NTFS permissions check has not been enabled.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
if (fi.permission(QFile::WriteUser | QFile::ReadGroup))
    qWarning("I can change the file; my group can read the file");
if (fi.permission(QFile::WriteGroup | QFile::WriteOther))
    qWarning("The group or others can change the file");

If the file is a symlink, this function checks the permissions of the target (not the symlink).

另请参阅 isReadable(), isWritable(), and isExecutable().

QFile::Permissions QFileInfo::permissions() const

Returns the complete OR-ed together combination of QFile::Permissions for the file.

注意 The result might be inaccurate on Windows if the NTFS permissions check has not been enabled.

If the file is a symlink, this function returns the permissions of the target (not the symlink).

void QFileInfo::refresh()

Refreshes the information about the file, i.e. reads in information from the file system the next time a cached property is fetched.

void QFileInfo::setCaching(bool enable)

If enable is true, enables caching of file information. If enable is false caching is disabled.

When caching is enabled, QFileInfo reads the file information from the file system the first time it's needed, but generally not later.

Caching is enabled by default.

另请参阅 refresh() and caching().

void QFileInfo::setFile(const QString &file)

Sets the file that the QFileInfo provides information about to file.

The file can also include an absolute or relative file path. Absolute paths begin with the directory separator (e.g. "/" under Unix) or a drive specification (under Windows). Relative file names begin with a directory name or a file name and specify a path relative to the current directory.

Example:

QString absolute = "/local/bin";
QString relative = "local/bin";
QFileInfo absFile(absolute);
QFileInfo relFile(relative);

QDir::setCurrent(QDir::rootPath());
// absFile and relFile now point to the same file

QDir::setCurrent("/tmp");
// absFile now points to "/local/bin",
// while relFile points to "/tmp/local/bin"

另请参阅 isFile(), isRelative(), QDir::setCurrent(), and QDir::isRelativePath().

void QFileInfo::setFile(const QFile &file)

This is an overloaded function.

Sets the file that the QFileInfo provides information about to file.

If file includes a relative path, the QFileInfo will also have a relative path.

另请参阅 isRelative().

void QFileInfo::setFile(const QDir &dir, const QString &file)

This is an overloaded function.

Sets the file that the QFileInfo provides information about to file in directory dir.

If file includes a relative path, the QFileInfo will also have a relative path.

另请参阅 isRelative().

qint64 QFileInfo::size() const

Returns the file size in bytes. If the file does not exist or cannot be fetched, 0 is returned.

If the file is a symlink, the size of the target file is returned (not the symlink).

另请参阅 exists().

QString QFileInfo::suffix() const

Returns the suffix (extension) of the file.

The suffix consists of all characters in the file after (but not including) the last '.'.

Example:

QFileInfo fi("/tmp/archive.tar.gz");
QString ext = fi.suffix();  // ext = "gz"

The suffix of a file is computed equally on all platforms, independent of file naming conventions (e.g., ".bashrc" on Unix has an empty base name, and the suffix is "bashrc").

另请参阅 fileName(), completeSuffix(), baseName(), and completeBaseName().

void QFileInfo::swap(QFileInfo &other)

Swaps this file info with other. This function is very fast and never fails.

This function was introduced in Qt 5.0.

QString QFileInfo::symLinkTarget() const

Returns the absolute path to the file or directory a symbolic link points to, or an empty string if the object isn't a symbolic link.

This name may not represent an existing file; it is only a string. QFileInfo::exists() returns true if the symlink points to an existing file.

This function was introduced in Qt 4.2.

另请参阅 exists(), isSymLink(), isDir(), and isFile().

bool QFileInfo::operator!=(const QFileInfo &fileinfo) const

Returns true if this QFileInfo object refers to a different file than the one specified by fileinfo; otherwise returns false.

另请参阅 operator==().

bool QFileInfo::operator==(const QFileInfo &fileinfo) const

Returns true if this QFileInfo object refers to a file in the same location as fileinfo; otherwise returns false.

Note that the result of comparing two empty QFileInfo objects, containing no file references (file paths that do not exist or are empty), is undefined.

警告 This will not compare two different symbolic links pointing to the same file.

警告 Long and short file names that refer to the same file on Windows are treated as if they referred to different files.

另请参阅 operator!=()

QFileInfoList

等同于 QList<QFileInfo>

QGenericArgument 类

QGenericArgument 类是用于序列化参数的内部辅助类。更多信息...

属性内容
头文件#include <QGenericArgument>
qmakeQT += core
被继承QGenericReturnArgument

公共成员函数

返回类型函数
QGenericArgument(const char *name = nullptr, const void *data = nullptr)
void *data() const
const char *name() const

详细描述

该类绝不应该被主动使用,请通过 Q_ARG() 来使用。

另请参阅:Q_ARG()、QMetaObject::invokeMethod() 和 QGenericReturnArgument

成员函数描述

QGenericArgument::QGenericArgument(const char *name = nullptr, const void *data = nullptr)

通过给定的 namedata 构造 QGenericArgument 对象。


void *QGenericArgument::data() const

返回构造函数中设置的数据对象指针。


const char *QGenericArgument::name() const

返回构造函数中设置的名称。

QGenericReturnArgument 类

QGenericReturnArgument 类是用于序列化返回值的内部辅助类。更多信息...

属性内容
头文件#include <QGenericReturnArgument>
qmakeQT += core
继承自QGenericArgument

公共成员函数

返回类型函数
QGenericReturnArgument(const char *name = nullptr, void *data = nullptr)

详细描述

该类绝不应该被主动使用,请通过 Q_RETURN_ARG() 来使用。

另请参阅:Q_RETURN_ARG(),QMetaObject::invokeMethod() 和 QGenericArgument

成员函数描述

QGenericReturnArgument::QGenericReturnArgument(const char *name = nullptr, void *data = nullptr)

通过给定的 namedata 构造 QGenericReturnArgument 对象。

Reserved by ZgblKylin until 2020-07-31

[TOC]

QIODevice Class

Reserved by Skykey until 2020-07-31

reserved by hqwx2018 until 2020-08-15

reserved by hqwx2018 until 2020-08-15

reserved by hqwx2018 until 2020-08-15

[TOC]

QJsonParseError Struct

QJsonParseError类用于在JSON解析期间报告错误。

属性方法
头文件:Header: #include
qmake:QT += core
从:Qt5.0

该结构在5.0被引入。

注意: 该结构的所有函数都是可重入.。

公共类型

类型枚举
enumParseError { NoError, UnterminatedObject, MissingNameSeparator, UnterminatedArray, MissingValueSeparator, …, GarbageAtEnd }

公共成员函数

类型函数名
QStringerrorString() const

公共变量

类型变量名
QJsonParseError::ParseErrorerror
intoffset

详细说明

另外参阅 JSON Support in QtJSON Save Game Example

成员类型文档

enum QJsonParseError::ParseError

该枚举描述了在解析JSON文档期间发生的错误类型。

不变量描述
QJsonParseError::NoError0没有发生错误
QJsonParseError::UnterminatedObject1对象未正确使用大括号
QJsonParseError::MissingNameSeparator2缺少分隔不同项目的逗号
QJsonParseError::UnterminatedArray3数组未正确用方括号括起来
QJsonParseError::MissingValueSeparator4缺少将键与对象内的值分隔开的冒号
QJsonParseError::IllegalValue5该值是非法的
QJsonParseError::TerminationByNumber6输入流在解析数字时结束
QJsonParseError::IllegalNumber7数字格式不正确
QJsonParseError::IllegalEscapeSequence8输入中发生非法的转义序列
QJsonParseError::IllegalUTF8String9输入中出现非法的UTF8序列
QJsonParseError::UnterminatedString10字符串未以引号终止
QJsonParseError::MissingObject11预期有对象,但找不到
QJsonParseError::DeepNesting12JSON文档的嵌套太深,解析器无法对其进行解析
QJsonParseError::DocumentTooLarge13JSON文档太大,解析器无法解析它
QJsonParseError::GarbageAtEnd14解析的文档末尾包含其他垃圾字符

公有成员函数文档

QString QJsonParseError::errorString() const

返回适合于所报告的JSON解析错误的人类可读消息。

另请参见error

成员变量文档

QJsonParseError::ParseError QJsonParseError::error

包含解析错误的类型。如果文档被正确解析,则等于QJsonParseError :: NoError

另外参阅 ParseErrorerrorString()。

int QJsonParseError::offset

包含发生解析错误的输入字符串中的偏移量。

另外参阅 errorerrorString()。

reserved by hqwx2018 until 2020-08-15

Reserved by leytou until 2020-07-31

QLibrary Class

Qlibrary用于运行时加载库。

属性内容
头文件:#include <QLibrary>
qmake:QT += core
继承于:QObject

注意: 此类中全部函数可重入。

公共成员类型

类型名称
enumLoadHint { ResolveAllSymbolsHint, ExportExternalSymbolsHint, LoadArchiveMemberHint, PreventUnloadHint, DeepBindHint }
flagsLoadHints

属性

公共成员函数

类型函数名
QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr)
QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr)
QLibrary(const QString &fileName, QObject *parent = nullptr)
QLibrary(QObject *parent = nullptr)
virtual~QLibrary()
QStringerrorString() const
QStringfileName() const
boolisLoaded() const
boolload()
QLibrary::LoadHintsloadHints() const
QFunctionPointer[resolve](-> #qfunctionpointer-qlibraryresolveconst-char-symbol)(const char *symbol)
voidsetFileName(const QString &fileName)
voidsetFileNameAndVersion(const QString &fileName, int versionNumber)
voidsetFileNameAndVersion(const QString &fileName, const QString &version)
voidsetLoadHints(QLibrary::LoadHints hints)
boolunload()

静态公共成员

类型函数名
boolisLibrary(const QString &fileName)
QFunctionPointerresolve(const QString &fileName, const char *symbol)
QFunctionPointerresolve(const QString &fileName, int verNum, const char *symbol)
QFunctionPointerresolve(const QString &fileName, const QString &version, const char *symbol)

详细描述

QLibrary的实例用于操作一个动态链接库文件(文中称为库,也就是DLL)。QLibrary提供访问库中函数的一种平台无关方式。您可以在构造时传递库文件名,也可以通过 setFileName() 给对象显式设置。加载库时,QLibrary在所有系统指定的位置搜索 (例如: Unix上的 LD_LIBRARY_PATH), 除非文件名是绝对路径。

如果文件路径是绝对路径,则会首先尝试在这个位置加载。如果找不到,QLibrary尝试不同系统相关的前后缀的文件名,比如Unix系的前缀“lib”,后缀“.so”,Mac及IOS的后缀".dylib",Windows的后缀".dll"。

如果文件路径不是绝对路径,Qlibrary改变搜索顺序,首先尝试系统特定的前后缀,之后是特定文件路径。

这让使用除去前后缀的库基本名称来指定库文件变得可能。因此代码可以在不同操作系统里执行,但不用太多代码尝试各种文件名称。

最重要的函数是 load() 用于动态加载库,isLoaded() 用于检查是否加载成功,以及 resolve() 来解析库中的符号。如果库还没加载,resolve() 函数隐式地加载这个库。多个QLibrary实例访问同一个物理库文件是可行的。一旦被加载,库在内存中一直保留到程序结束。您可以通过 unload() 尝试卸载一个库,但如果有其他QLibrary实例在使用同一个库文件,调用会失败。只有在每一个实例都调用过 unload() 后,库才会真正卸载。

Qlibrary 的一种典型用法是解析库中的导出符号,并调用其对应的C语言函数。这叫做显式链接,对应于隐式链接。隐式链接是构建中的链接可执行文件和静态库的步骤。

下面的代码片段加载了个库,解析"mysymbol"符号,并在一切就绪的情况下调用这个函数。如果出现了问题, 例如库文件不存在或者符号未定义,函数指针将会是nullptr,且不会调用。

QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
    myFunction();

符号必须作为C函数导出,resolve()才能工作。这意味着用C++编译器编译的函数必须由extern "C"块包裹。在Windows上,还要求导出函数要使用dllexport宏;实现详情见 resolve()。方便起见,resolve() 函数有静态形式,您可以在不现实加载库的情况下使用:

typedef void (*MyPrototype)();
MyPrototype myFunction =
        (MyPrototype) QLibrary::resolve("mylib", "mysymbol");
if (myFunction)
    myFunction();

另请参阅: QPluginLoader.

成员类型介绍

enum QLibrary::LoadHint flags QLibrary::LoadHints

这个枚举描述了可能的可以用来改变库的加载行为的指示。这些取值指示在库加载后如何解析符号,通过 setLoadHints() 指定。

常量描述
QLibrary::ResolveAllSymbolsHint0x01在加载库的时候解析符号,而不是简单等到 resolve() 调用。
QLibrary::ExportExternalSymbolsHint0x02导出库中未解析的符号和外部符号,这些符号可以在后续动态加载的库中解析。
QLibrary::LoadArchiveMemberHint0x04运行库的文件名指定压缩包中的特定对象。如果设置了这个指示,文件名包含一个路径,其指向归档文件,接着是其中的成员名称。
QLibrary::PreventUnloadHint0x08阻止库从地址空间通过close()卸载。如果之后再有open()调用,库中的静态变量不会重新初始化。
QLibrary::DeepBindHint0x10Instructs the linker to prefer definitions in the loaded library over exported definitions in the loading application when resolving external symbols in the loaded library. This option is only supported on Linux.
命令链接器在解析加载过的库中的外部符号时,优先使用加载了的库中的定义,而不是在应用程序加载中的定义。【译者注:翻译存疑,故保留原文参考,详情参考globc--dlopen()--RTLD_DEEPBIND】

LoadHints是一个 QFlags<LoadHint> 类型的typedef。 它储存了LoadHint取值的OR(位或)方式的组合。

另请参阅: loadHints.

属性文档

fileName : QString

这个属性容纳库的文件名。

我们建议忽略库的后缀名,因为Qlibrary会自动寻找带有合适后缀名的文件。 (参见 isLibrary())

当加载库时,在所有系统指定的位置搜索 (例如: Unix上的 LD_LIBRARY_PATH),除非文件名是绝对路径。加载成功后,fileName() 返回返回库文件的全名。如果在构造对象或setFileName() 中包含路径,讲返回文件的全路径。

例如在Unix平台成功加载"GL"库后,fileName() 会返回 "libGL.so"。如果传递参数的文件路径是 "/usr/lib/libGL", fileName() 会返回 "/usr/lib/libGL.so"。

访问函数:

类型函数名
QStringfileName() const
voidsetFileName(const QString &fileName)

loadHints : LoadHints

load() 函数一些关于如何执行的指示。

您可以对于符号如何解析做指示。通常来说,符号不是在加载库时解析的,而是惰性解析的(也就是调用 resolve() 时)。如果您设置loadHints 为ResolveAllSymbolsHint,那么如果平台支持,所有符号会在库加载时一齐解析。

设置 ExportExternalSymbolsHint 会使库中的外部符号在后续库解析中可用。

如果设置了 LoadArchiveMemberHint ,文件名会被分解为两部分:归档文件的路径和归档成员的名称. 例如, fileName libGL.a(shr_64.o) 指向归档文件 libGL.a中的库文件 shr_64.o . 这个特性只在AIX平台生效。

loadHints 的解释是平台相关的,如果您用这些特效,您大概已经对编译的系统平台做了一些假设。因此请仅在您明白您这些操作的结果的情况下设置这些指示。

默认情况下,此属性没有设置任何flag,所有库文件会惰性加载,并且不会导出共其他动态链接库使用的外部符号。

注意: 在库已经加载后设置这个属性没有效果。 并且 loadHints() 不会体现出这些修改。

注意: 这个属性是所有指向同一个库的 QLibrary 实例共享的。

访问函数:

类型函数名
QLibrary::LoadHintsloadHints() const
voidsetLoadHints(QLibrary::LoadHints hints)

成员函数文档

QLibrary::QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr)

基于给定的父对象 parent 构造一个库对象。它会加载文件名fileName、完整版本号 version 指定的库文件。如今,版本号在Windows上被忽略。

我们建议在 fileName 中忽略文件名的前后缀,因为QLibrary会基于不同平台自动寻找合适的前后缀。比如Unix系的前缀“lib”,后缀“.so”,Mac及IOS的后缀".dylib",Windows的后缀".dll"。(参见fileName


QLibrary::QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr)

基于给定的父对象 parent 构造一个库对象。它会加载文件名fileName、主版本号 verNum 指定的库文件。如今,版本号在Windows上被忽略。

我们建议在 fileName 中忽略文件名的前后缀,因为QLibrary会基于不同平台自动寻找合适的前后缀。比如Unix系的前缀“lib”,后缀“.so”,Mac及IOS的后缀".dylib",Windows的后缀".dll"。(参见fileName


QLibrary::QLibrary(const QString &fileName, QObject *parent = nullptr)

基于给定的父对象 parent 构造一个库对象。它会加载文件名fileName 指定的库文件。

我们建议在 fileName 中忽略文件名的前后缀,因为QLibrary会基于不同平台自动寻找合适的前后缀。比如Unix系的前缀“lib”,后缀“.so”,Mac及IOS的后缀".dylib",Windows的后缀".dll"。(参见fileName


QLibrary::QLibrary(QObject *parent = nullptr)

基于给定的父对象 parent 构造一个库对象。


[virtual]QLibrary::~QLibrary()

删除此QLibrary对象。

除非显式调用 unload(),库会在一直驻留在内存中,知道应用结束。

另请参阅: isLoaded() 和 unload().


QString QLibrary::errorString() const

返回一个描述上一个发生的错误的文本字符串。截至现在,errorString 只会在 load(), unload() 或 resolve() 调用由于一些原因失败时才会设置。

此函数引入自:Qt 4.2.


[static]bool QLibrary::isLibrary(const QString &fileName)

如果 fileName 包含一个合法的可加载的后缀,返回true;否则返回false。

平台合法后缀
Windows.dll, .DLL
Unix/Linux.so
AIX.a
HP-UX.sl, .so (HP-UXi)
macOS and iOS.dylib, .bundle, .so

Unix平台上的名字后的版本号会被忽略。


bool QLibrary::isLoaded() const

如果库已经被加载,返回true,否则返回false。

另请参阅: load().


bool QLibrary::load()

加载一个库,如果成功加载则返回true;否则返回false。因为 resolve() 内部会自动调用此方法,您没必要显示调用这个函数。如果在某些情况下您想提前加载库,您可以主动调用它。

另请参阅: unload().


QFunctionPointer QLibrary::resolve(const char *symbol)

返回导出符号 symbol 对应的地址。如果需要,库会自动加载。如果库无法加载或符号无法解析,返回 nullptr

例如:

typedef int (*AvgFunction)(int, int);

AvgFunction avg = (AvgFunction) library->resolve("avg");
if (avg)
    return avg(5, 8);
else
    return -1;

符号必须作为C语言函数导出。这意味着如果使用C++编译器,函数必须由 extern "C" 包裹。在Windows平台,您还必须显式通过 __declspec(dllexport) 指导编译器导出符号,例如:

extern "C" MY_EXPORT int avg(int a, int b)
{
    return (a + b) / 2;
}

MY_EXPORT 定义如下

#ifdef Q_OS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif

[static]QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)

这是一个重载函数。

加载文件名 fileName 对应的库,并返回 symbol 对应导出符号的地址。注意 fileName 不应该包含平台相关前后缀(详情见 fileName). 库会一直保留到应用程序退出。

如果库无法加载或符号无法解析,返回 nullptr

另请参阅: resolve().


[static]QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char**symbol*)

这是一个重载函数。

加载文件名 fileName 、主版本号 verNum 对应的库,并返回 symbol 对应导出符号的地址。注意 fileName 不应该包含平台相关前后缀(详情见 fileName). 库会一直保留到应用程序退出。version 参数在 Windows 上无效。

如果库无法加载或符号无法解析,返回 nullptr

另请参阅: resolve().


[static]QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)

这是一个重载函数。

加载文件名 fileName 、完整版本号 version 对应的库,并返回 symbol 对应导出符号的地址。注意 fileName 不应该包含平台相关前后缀(详情见 fileName). 库会一直保留到应用程序退出。version 参数在 Windows 上无效。

如果库无法加载或符号无法解析,返回 nullptr

此函数引入自:Qt 4.4.

另请参阅: resolve().

void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)

设置 fileName 属性,以及相对应的文件名和版本号信息。versionNumber 参数在 Windows 上无效。

另请参阅: setFileName().

void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)

设置 fileName 属性,以及相对应的文件名和完整版本号信息。version 参数在 Windows 上无效。

此函数引入自:Qt 4.4.

另请参阅: setFileName().

bool QLibrary::unload()

卸载一个库;如果成功返回true,否则false

在应用程序结束是,此函数自动调用,因此您不应该手动调用。

如果有其他 QLibrary 示例在使用同一个库,调用会失败。卸载只会在所有实例都调用过此函数之后发生。

注意:在 Mac OS X 10.3 (Panther),无法卸载动态链接库。

另请参阅: resolve() 和 load().

QList Class

template <typename T> class QList

QList 类是一个用于提供列表支持的模板类。更多...

头文件:#include
qmake:QT += core
子类:QByteArrayList, QItemSelection, QQueueQStringList

注意: 本页面提到的方法都是可重入的

公共成员类型

classconst_iterator
classiterator
typedefConstIterator
typedefIterator
typedefconst_pointer
typedefconst_reference
typedefconst_reverse_iterator
typedefdifference_type
typedefpointer
typedefreference
typedefreverse_iterator
typedefsize_type
typedefvalue_type

公共成员方法

QList(InputIterator first, InputIterator last)
QList(std::initializer_list args)
QList(QList &&other)
QList(const QList &other)
QList()
QList &operator=(QList &&other)
QList &operator=(const QList &other)
~QList()
voidappend(const T &value)
voidappend(const QList &value)
const T &at(int i) const
T &back()
const T &back() const
QList::iteratorbegin()
QList::const_iteratorbegin() const
QList::const_iteratorcbegin() const
QList::const_iteratorcend() const
voidclear()
QList::const_iteratorconstBegin() const
QList::const_iteratorconstEnd() const
const T &constFirst() const
const T &constLast() const
boolcontains(const T &value) const
intcount(const T &value) const
intcount() const
QList::const_reverse_iteratorcrbegin() const
QList::const_reverse_iteratorcrend() const
boolempty() const
QList::iteratorend()
QList::const_iteratorend() const
boolendsWith(const T &value) const
QList::iteratorerase(QList::iterator pos)
QList::iteratorerase(QList::iterator begin, QList::iterator end)
T &first()
const T &first() const
T &front()
const T &front() const
intindexOf(const T &value, int from = 0) const
voidinsert(int i, const T &value)
QList::iteratorinsert(QList::iterator before, const T &value)
boolisEmpty() const
T &last()
const T &last() const
intlastIndexOf(const T &value, int from = -1) const
intlength() const
QListmid(int pos, int length = -1) const
voidmove(int from, int to)
voidpop_back()
voidpop_front()
voidprepend(const T &value)
voidpush_back(const T &value)
voidpush_front(const T &value)
QList::reverse_iteratorrbegin()
QList::const_reverse_iteratorrbegin() const
intremoveAll(const T &value)
voidremoveAt(int i)
voidremoveFirst()
voidremoveLast()
boolremoveOne(const T &value)
QList::reverse_iteratorrend()
QList::const_reverse_iteratorrend() const
voidreplace(int i, const T &value)
voidreserve(int alloc)
intsize() const
boolstartsWith(const T &value) const
voidswap(QList &other)
voidswapItemsAt(int i, int j)
TtakeAt(int i)
TtakeFirst()
TtakeLast()
QSettoSet() const
std::listtoStdList() const
QVectortoVector() const
Tvalue(int i) const
Tvalue(int i, const T &defaultValue) const
booloperator!=(const QList &other) const
QListoperator+(const QList &other) const
QList &operator+=(const QList &other)
QList &operator+=(const T &value)
QList &operator<<(const QList &other)
QList &operator<<(const T &value)
booloperator==(const QList &other) const
T &operator[](int i)
const T &operator[](int i) const

静态公共成员

QListfromSet(const QSet &set)
QListfromStdList(const std::list &list)
QListfromVector(const QVector &vector)

相关非成员函数

uintqHash(const QList &key, uint seed = 0)
booloperator<(const QList &lhs, const QList &rhs)
QDataStream &operator<<(QDataStream &out, const QList &list)
booloperator<=(const QList &lhs, const QList &rhs)
booloperator>(const QList &lhs, const QList &rhs)
booloperator>=(const QList &lhs, const QList &rhs)
QDataStream &operator>>(QDataStream &in, QList &list)

详细描述

QListQt 泛型容器之一,通过列表保存元素,提供了基于索引的快速访问以及基于索引的插入和删除功能。

QList,QLinkedListQVector 提供了类似的接口和功能。 大部分情况下它们之间是可以互相替换的,但可能会带来一些性能问题。这里有一个各自适用场景的总结:

  • QVector 应当是你的默认首选。QVector 的性能通常要优于 QList, 因为 QVector 总是在内存中连续存储其元素,而 QList 则只会在sizeof(T) <= sizeof(void*) 且通过 Q_DECLARE_TYPEINFO 将 T 声明为 Q_MOVABLE_TYPEQ_PRIMITIVE_TYPE 的情况下才会这么做,否则将会在堆上分配其元素的内存。QList 使用利弊分析 一文对此做了解释。
  • 然而,QList 在 Qt API 中总是被用来传递参数和保存返回值,和这些 API 交互时请使用 QList。
  • 如果你需要一个真正的基于链表实现的列表,以保证列表中间插入元素是常量时间复杂度以及基于迭代器而不是索引来访问元素,你可以使用 QLinkedList。

注意: QVectorQVarLengthArray 都提供了对 C 数组内存布局的兼容,但 QList 不保证这一点。这一点在你的应用需要和 C API 交互时可能会非常重要。

注意: QLinkedList 的迭代器和在堆上分配内存的 QList 的引用只要其指向的元素还在容器中,将会一直保持有效。但 QVector 和非在堆上分配内存的的 QList 的迭代器以及引用并不保证这一点。

内部实现中,如果 sizeof(T) <= sizeof(void*) 且通过 Q_DECLARE_TYPEINFO 将 T 声明为 Q_MOVABLE_TYPEQ_PRIMITIVE_TYPE 时,QList 将表现为一个 T 类型的数组。否则,QList 表现为一个 T* 类型的数组,元素实际在堆上分配内存。

基于数组的实现的 QList 支持快速插入和基于索引的访问。prepend() and append() 操作也非常快,因为 QList 在内部数组的头尾均预分配了内存。(详见算法复杂度

注意,如果上面的条件不能满足,每一次追加或插入一个新的元素都需要在堆上分配这个新元素的内存。这会导致在有大量元素的追加和插入时使用 QVector 成为一个更好的选择,因为 QVector 可以在一次性为多个元素在堆上分配内存。

另一个需要注意的是内部数组在列表的整个生命周期内只会不断增大,永远不会缩小。内部数组将会在列表析构时调用的析构函数或列表被赋予另一个列表时调用的赋值运算符函数中被析构。

下方是使用 QList 保存整型数字和使用 QList 保存 QDate 的例子:

QList<int> integerList;
QList<QDate> dateList;

Qt 提供了 QStringList 类,其继承于 QList<QString> ,提供了一些快捷方法,例如 QStringList::join() 和 QStringList::filter()。QString::split() 用于从 QString 创建 QStringList。

QList 以列表的形式保存元素,默认构造函数会创建一个空列表,你可以使用带有初始化列表的构造函数创建出一个带有元素的的列表:

QList<QString> list = { "one", "two", "three" };

QList 提供了这些基础方法用于添加,移动和删除元素:insert(), replace(), removeAt(), move() 和 swap()。另外,它还提供了下列快捷方法:append(), operator<<(), operator+=(), prepend(), removeFirst() 和 removeLast()。

operator<<() 可以方便地添加多个元素到列表中:

list << "four" << "five";

和 C++ 数组一样,QList 索引从 0 开始。要访问在指定位置的元素,你可以使用 operator[]()。对于非常量列表,operator[]() 用于返回一个元素的引用,可以被用在赋值运算符的左侧(译注:即可作为左值):

if (list[0] == "Bob")
    list[0] = "Robert";

由于对于大小大于一个指针或不可移动的元素类型,QList 基于该类型的指针数组实现,因此该操作需要(常量时间复杂度)。对于只读访问,一个可替代的语法是使用 at():

for (int i = 0; i < list.size(); ++i) {
    if (list.at(i) == "Jane")
        cout << "Found Jane at position " << i << Qt::endl;
}

at() 可能会比 operator[]() 快,因为其永远不会导致深拷贝的发生。

从列表中移除一个元素,然后对其做一些处理是一个很常用的操作。QList 提供了 takeAt(), takeFirst() 和 takeLast() 来实现该操作。下面是一个将元素逐个从列表中移除并对该元素调用 delete 的循环实现:

QList<QWidget *> list;
..。
while (!list.isEmpty())
    delete list.takeFirst();

在列表两端插入或删除元素是非常快的(通常是常量时间复杂度),因为QList在内部缓存的两端都预分配了额外的内存空间用于支持列表两端的快速增长。

如果需要在列表中查找所有特定值的元素的索引,可以使用 indexOf() 或 lastIndexOf()。前一个用于从给定的索引位置向列表尾部方向查找,后一个则相反。二者都会在找到时返回匹配元素的索引,未找到时返回 -1。例如:

int i = list.indexOf("Jane");
if (i != -1)
    cout << "Jane 首次出现的位置是 " << i << Qt::endl;

如果你仅仅是想简单地检查特定值是否存在于列表中,可以使用 contains()。如果你想要统计特定值在列表中出现的次数,可以使用 count()。如果你想将所有特定值替换为一个另一个指定值,可以使用 replace()。

QList 中的元素类型必须是 可赋值数据类型。绝大部分常用数据类型都满足这一点,但某些情况编译器可能会报错,例如以值的形式保存 QWidget,可改成保存 QWidget * 来代替。一些方法会有额外的要求,例如,indexOf() 和 lastIndexOf() 要求值类型支持 operator==() 运算符。这些要求在每个函数的文档中有说明。

正如其他的容器类一样,QList 提供了 Java 风格迭代器(QListIteratorQMutableListIterator) 和 STL 风格迭代器 (QList::const_iteratorQList::iterator)。实际使用中,这些迭代器其实很少被使用,因为你可以使用列表索引。QList 的实现使得直接基于索引访问的方式实现和使用迭代器一样快。

QList 并 支持通过其元素的引用来进行插入,头部追加,尾部追加和替换,这样做会导致你的应用崩溃并显示错误信息。

为了使 QList 尽可能高效,其成员函数在使用前并不会对输入进行校验,但 isEmpty() 例外,成员函数通常会假定列表 为空。带有索引值作为参数的的成员函数总是会假定索引值位于合法的范围内。这意味着 QList 成员函数可能会调用失败。如果在编译时定义了 QT_NO_DEBUG,这些错误将不会被检测到。而如果 没有 定义 QT_NO_DEBUG,此类错误将会通过 Q_ASSERT() 或 Q_ASSERT_X() 被检测到并显示对应的错误信息。

为了避免在在列表可能为空时报错,在调用其他成员函数前应先调用 isEmpty() 检查。如果你必须传递一个可能不在有效范围内的索引值,应先检查其是否小于 size() 的返回值且 小于0。

更多成员

如果 T 是 QByteArray 类型,这个类会提供更多可以使用的成员,详见 QByteArrayList

如果 T 是 QString 类型,这个类提供了这些额外的成员函数:filter, join, removeDuplicates, sort

使用 Qt 容器的更多信息

如果想要详细了解 Qt 和 STL 对应容器之间的对比,可阅读 理解 Qt 容器一文。

另请参阅: QListIterator, QMutableListIterator, QLinkedListQVector

成员类型文档

typedef QList::ConstIterator

Qt 风格的 QList::const_iterator 的同义词。

typedef QList::Iterator

Qt 风格的 QList::iterator 的同义词。

typedef QList::const_pointer

const T * 的类型别名,提供了对 STL 的兼容。

typedef QList::const_reference

const T & 的类型别名,提供了对 STL 的兼容。

typedef QList::const_reverse_iterator

QList::const_reverse_iterator 仅仅是 std::reverse_iterator<const_iterator> 的类型别名,用于提供 STL 风格的 QList 常量反向迭代器。

警告: 支持隐式共享的容器的迭代器的行为和 STL 迭代器并不完全一样。当这类容器的迭代器在使用时你应当避免容器的拷贝。更多信息请阅读 隐式共享迭代器问题 一文。

该类型在 Qt 5.6 中引入。

另请参阅 QList::rbegin(), QList::rend(), QList::reverse_iteratorQList::const_iterator

typedef QList::difference_type

ptrdiff_t 的别名,提供了对 STL 的兼容。

typedef QList::pointer

T * 的别名,提供了对 STL 的兼容。

typedef QList::reference

T & 的别名,提供了对 STL 的兼容。

typedef QList::reverse_iterator

QList::reverse_iterator 仅仅是 std::reverse_iterator<iterator> 的类型别名,用于提供 STL 风格的 QList 非常量反向迭代器。

警告: 支持隐式共享的容器的迭代器的行为和 STL 迭代器并不完全一样。当这类容器的迭代器在使用时你应当避免容器的拷贝。更多信息请阅读 隐式共享迭代器问题 一文。

该类型在 Qt 5.6 中引入。

另请参阅 QList::rbegin(), QList::rend(), QList::const_reverse_iteratorQList::iterator

typedef QList::size_type

int 类型的别名,提供了对 STL 的兼容。

typedef QList::value_type

T 类型的别名,提供了对 STL 的兼容。

成员函数文档

template QList::QList(InputIterator first, InputIterator last)

使用迭代器范围 [first, last)指定的内容构造一个 QList。

InputIterator 的值类型必须可转换为 T

该方法在 Qt 5.14 中引入。

QList::QList(std::initializer_list args)

从由 args 指定的 std::initializer_list 构造一个列表。

此构造函数仅在编译器支持 C++11 初始化列表特性时可用。

该方法在 Qt 4.8 中引入。

QList::QList(QList &&other)

移动构造一个 QList 实例,使它和 other 指向同一个对象。

该方法在 Qt 5.2 中引入。

QList::QList(const QList &other)

构造一个 other 的拷贝。

该操作为 常量时间复杂度,因为 QList 是隐式共享的,所以一个函数返回 QList 是非常快的。如果一个共享实例被修改了,其将会被复制一份(写时拷贝),复杂度为线性时间复杂度

另请参阅 operator=()。

QList::QList()

构造一个空列表。

QList &QList::operator=(QList &&other)

移动赋值 other 给该 QList 实例。

该方法在 Qt 5.2 中引入。

QList &QList::operator=(const QList &other)

other 赋值给当前列表,然后返回当前列表的引用。

QList::~QList()

析构列表。列表中的值的引用及所有的迭代器都将失效。

void QList::append(const T &value)

插入 value 到列表尾部。

示例:

QList<QString> list;
list.append("one");
list.append("two");
list.append("three");
// list: ["one", "two", "three"]

该方法等同于 list.insert(size(), value)。

如果该列表是非共享的,那么此操作通常会非常快(均摊下来为 常量时间复杂度),因为QList 在内部缓存的两端都预分配了额外的内存空间用于支持列表两端的快速增长。

另请参阅 operator<<(), prepend() 和 insert()。

void QList::append(const QList &value)

这是个重载函数。

插入另一个列表 value 中的元素到列表尾部。

该方法在 Qt 4.5 中引入。

另请参阅 operator<<() 和 operator+=()。

const T &QList::at(int i) const

返回位于列表索引位置为 i 的元素。i 必须是列表中合法的索引位置 (例如,0 <= i < size())。

该方法非常快,为(常量时间复杂度)。

另请参阅 value() 和 operator[]()。

T &QList::back()

该方法用于提供对 STL 的兼容,等同于 last()。该方法要求列表不能为空, 如果列表可能为空,应先调用 isEmpty() 进行检查。

const T &QList::back() const

这是个重载函数。

QList::iterator QList::begin()

返回一个指向列表第一个元素的 STL 风格迭代器

另请参阅 constBegin() 和 end()。

QList::const_iterator QList::begin() const

这是个重载函数。

QList::const_iterator QList::cbegin() const

返回指向列表中第一个元素的常量 STL 风格迭代器

该方法在 Qt 5.0 中引入。

另请参阅 begin() and cend()。

QList::const_iterator QList::cend() const

返回一个指向位于最后一个元素之后的虚拟元素的常量 STL 风格迭代器

该方法在 Qt 5.0 中引入。

另请参阅 cbegin() and end()。

void QList::clear()

移除列表中所有的元素。

另请参阅 removeAll()。

QList::const_iterator QList::constBegin() const

返回指向列表中第一个元素的常量 STL 风格迭代器

另请参阅 begin() 和 constEnd()。

QList::const_iterator QList::constEnd() const

返回一个指向位于最后一个元素之后的虚拟元素的常量 STL 风格迭代器

另请参阅 constBegin() 和 end()。

const T &QList::constFirst() const

返回一个列表中第一个元素的常量引用,列表必须不为空。如果列表可能为空,应先调用 isEmpty() 进行检查。

该方法在 Qt 5.6 中引入。

另请参阅 constLast(), isEmpty() 和 first()。

const T &QList::constLast() const

返回一个列表中最后一个元素的常量引用,列表必须不为空。如果列表可能为空,应先调用 isEmpty() 进行检查。

该方法在 Qt 5.6 中引入。

另请参阅 constFirst(), isEmpty() 和 last()。

bool QList::contains(const T &value) const

如果列表中包含 value 则返回 true,否则返回false

该方法要求值类型实现了 operator==()

另请参阅 indexOf() 和 count()。

int QList::count(const T &value) const

返回 value 在列表中的出现次数。

该方法要求值类型实现了 operator==()

另请参阅 contains() 和 indexOf()。

int QList::count() const

返回列表中元素的数量。该方法的性能等同于 size()。

QList::const_reverse_iterator QList::crbegin() const

返回指向逆序列表的第一个元素的常量 STL 风格迭代器

该方法在 Qt 5.6 中引入。

另请参阅 begin(), rbegin() 和 rend()。

QList::const_reverse_iterator QList::crend() const

返回指向逆序列表的最后一个元素的下一个元素的常量 STL 风格迭代器

该方法在 Qt 5.6 中引入。

另请参阅 end(), rend() 和 rbegin()。

bool QList::empty() const

该方法用于提供对 STL 的兼容,等同于 isEmpty(),当列表为空时返回 true

QList::iterator QList::end()

返回一个指向位于最后一个元素之后的虚拟元素的常量 STL 风格迭代器

另请参阅 begin() 和 constEnd()。

QList::const_iterator QList::end() const

这是个重载函数。

bool QList::endsWith(const T &value) const

如果列表非空且最后一个元素等于 value 则返回true 否则返回 false

该方法在 Qt 4.5 中引入。

另请参阅 isEmpty() 和 contains()。

QList::iterator QList::erase(QList::iterator pos)

从列表中移除和迭代器 pos 关联的元素,然会返回列表中下一个元素的迭代器 (可能是 end())。

另请参阅 insert() 和 removeAt()。

QList::iterator QList::erase(QList::iterator begin, QList::iterator end)

这是个重载函数。

移除从 begin 到 (但不包括) end 的所有元素,然会返回调用该方法之前 end 所指向元素的迭代器。

T &QList::first()

返回列表中第一个元素的引用,列表必须非空。如果列表可能为空,应先调用 isEmpty() 进行检查。

另请参阅 constFirst(), last() 和 isEmpty()。

const T &QList::first() const

这是个重载函数。

[static] QList QList::fromSet(const QSet &set)

返回一个包含且仅包含 set 中所有的数据的 QList 对象。QList 中元素的顺序是未定义的。

示例:

QSet<int> set;
set << 20 << 30 << 40 << ... << 70;

QList<int> list = QList<int>::fromSet(set);
std::sort(list.begin(), list.end());

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 fromVector(), toSet() 和 QSet::toList()。

[static] QList QList::fromStdList(const std::list &list)

返回一个包含且仅包含 list 中所有的数据的 QList 对象。QList 中元素的顺序和 list 一致。

示例:

std::list<double> stdlist;
list.push_back(1.2);
list.push_back(0.5);
list.push_back(3.14);

QList<double> list = QList<double>::fromStdList(stdlist);

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 toStdList() 和 QVector::fromStdVector()。

[static] QList QList::fromVector(const QVector &vector)

返回包含且仅包含 vector 中所有的元素的 QList 对象。

示例:

QVector<double> vect;
vect << 20.0 << 30.0 << 40.0 << 50.0;

QList<double> list = QVector<T>::fromVector(vect);
// list: [20.0, 30.0, 40.0, 50.0]

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 fromSet(), toVector() 和 QVector::toList()。

T &QList::front()

该方法用于提供对 STL 的兼容,等同于 first()。要求列表不能为空, 如果列表可能为空,应先调用 isEmpty() 进行检查。

const T &QList::front() const

这是个重载函数。

int QList::indexOf(const T &value, int from = 0) const

返回从索引位置 from 开始向列表尾部方向搜索,在列表中 value 第一次出现的索引位置。如果没有找到则返回 -1。

示例:

QList<QString> list;
list << "A" << "B" << "C" << "B" << "A";
list.indexOf("B");          // 返回 1
list.indexOf("B", 1);       // 返回 1
list.indexOf("B", 2);       // 返回 3
list.indexOf("X");          // 返回 -1

该方法要求值类型实现了 operator==()

需要注意的是 QList 和 C 数组类似,索引也是从 0 开始。除了上面提到的值,其他的负索引值不被支持。

另请参阅 lastIndexOf() 和 contains()。

void QList::insert(int i, const T &value)

value 插入到列表的索引位置 i

如果 i == 0,该值将会被追加到列表头部。如果 i == size(),该值将会被追加到列表尾部。

示例:

QList<QString> list;
list << "alpha" << "beta" << "delta";
list.insert(2, "gamma");
// list: ["alpha", "beta", "gamma", "delta"]

另请参阅 append(), prepend(), replace() 和 removeAt()。

QList::iterator QList::insert(QList::iterator before, const T &value)

这是个重载函数。

value 插入到迭代器 before 指向元素的前面,并返回一个指向插入元素的迭代器。需要注意的是传递给该函数的迭代器在调用完成后将会失效,返回的迭代器可以用来代替它。

bool QList::isEmpty() const

如果列表中没有任何元素则返回 true ,否则返回 false

另请参阅 size()。

T &QList::last()

返回列表最后一个元素的引用,列表必须非空。如果列表可能为空,应先调用 isEmpty() 进行检查。

另请参阅 constLast(), first() 和 isEmpty()。

const T &QList::last() const

这是个重载函数。

int QList::lastIndexOf(const T &value, int from = -1) const

返回从索引位置 from 开始向列表头部方向搜索,在列表中 value 最后一次出现的索引位置。如果 from 是 -1,将会从最后一个元素开始搜索。如果没有找到则返回 -1。

示例:

QList<QString> list;
list << "A" << "B" << "C" << "B" << "A";
list.lastIndexOf("B");      // 返回 3
list.lastIndexOf("B", 3);   // 返回 3
list.lastIndexOf("B", 2);   // 返回 1
list.lastIndexOf("X");      // 返回 -1

该方法要求值类型实现了 operator==()

需要注意的是 QList 和 C 数组类似,索引也是从 0 开始。除了上面提到的值,其他的负索引值不被支持。

另请参阅 indexOf()。

int QList::length() const

该方法等同于 count()。

该方法在 Qt 4.5 中引入。

另请参阅 count()。

QList QList::mid(int pos, int length = -1) const

返回一个包含从列表的 pos 位置开始的元素的子列表,如果 length 为 -1(默认值),那么从 pos 开始的所有元素都会被子列表包含,否则子列表将会包含 length 个(如果剩余元素个数不足length 则为剩下的全部)元素。

void QList::move(int from, int to)

将位于索引位置 from 的元素移动到索引位置 to

示例:

QList<QString> list;
list << "A" << "B" << "C" << "D" << "E" << "F";
list.move(1, 4);
// list: ["A", "C", "D", "E", "B", "F"]

等同于 insert(to, takeAt(from))。该方法会假定 fromto 都不小于 0 且小于 size()。为了避免调用出错,应提前检查 fromto 是否不小于 0 且小于 size()。

另请参阅 swap(), insert() 和 takeAt()。

void QList::pop_back()

该方法用于提供对 STL 的兼容,等同于 removeLast()。该方法要求列表不能为空,如果列表可能为空,应先调用 isEmpty() 进行检查。

void QList::pop_front()

该方法用于提供对 STL 的兼容,等同于 removeFirst()。该方法要求列表不能为空,如果列表可能为空,应先调用 isEmpty() 进行检查。

void QList::prepend(const T &value)

在列表头部插入 value

示例:

QList<QString> list;
list.prepend("one");
list.prepend("two");
list.prepend("three");
// list: ["three", "two", "one"]

该方法等同于 list.insert(0, value)。

如果该列表是非共享的,那么此操作通常会非常快(均摊下来为 常量时间复杂度),因为 QList 在内部缓存的两端都预分配了额外的内存空间用于支持列表两端的快速增长。

另请参阅 append() 和 insert()。

void QList::push_back(const T &value)

该方法用于提供对 STL 的兼容,等同于 append(value)。

void QList::push_front(const T &value)

该方法用于提供对 STL 的兼容,等同于 prepend(value)。

QList::reverse_iterator QList::rbegin()

返回一个指向列表在逆序遍历时第一个元素 STL 风格的反向迭代器。

该方法在 Qt 5.6 中引入。

另请参阅 begin(), crbegin() 和 rend()。

QList::const_reverse_iterator QList::rbegin() const

这是个重载函数。

该方法在 Qt 5.6 中引入。

int QList::removeAll(const T &value)

移除列表中所有值为 value 的元素,然后返回移除的数量。

示例:

QList<QString> list;
list << "sun" << "cloud" << "sun" << "rain";
list.removeAll("sun");
// list: ["cloud", "rain"]

该方法要求值类型实现了 operator==()

另请参阅 removeOne(), removeAt(), takeAt() 和 replace()。

void QList::removeAt(int i)

移除位于索引位置 i 的元素。i 必须是列表中的合法索引位置 (即 0 <= i < size())。

另请参阅 takeAt(), removeFirst(), removeLast() 和 removeOne()。

void QList::removeFirst()

移除列表中的第一个元素,等同于调用 removeAt(0)。该方法要求列表不能为空,如果列表可能为空,应先调用 isEmpty() 进行检查。

另请参阅 removeAt() 和 takeFirst()。

void QList::removeLast()

移除列表中最后一个元素,等同于调用 removeAt(size() - 1)。该方法要求列表不能为空,如果列表可能为空,应先调用 isEmpty() 进行检查。

另请参阅 removeAt() 和 takeLast()。

bool QList::removeOne(const T &value)

移除列表中第一个值为 value 的元素,若找到并移除成功则返回 true,否则返回 false

示例:

QList<QString> list;
list << "sun" << "cloud" << "sun" << "rain";
list.removeOne("sun");
// list: ["cloud", "sun", "rain"]

该方法要求值类型实现了 operator==()

该方法在 Qt 4.4 中引入。

另请参阅 removeAll(), removeAt(), takeAt() 和 replace()。

QList::reverse_iterator QList::rend()

返回一个指向列表在逆序遍历下最后一个元素的后一个元素的 STL 风格的反向迭代器。

该方法在 Qt 5.6 中引入。

另请参阅 end(), crend() 和 rbegin()。

QList::const_reverse_iterator QList::rend() const

这是个重载函数。

该方法在 Qt 5.6 中引入。

void QList::replace(int i, const T &value)

将位于索引位置 i 的元素替换为 valuei 必须是列表中合法的索引位置 (即 0 <= i < size())。

另请参阅 operator[]() 和 removeAt()。

void QList::reserve(int alloc)

预留 alloc 个元素的空位。

如果 alloc 比当前列表的长度要小,则无事发生。

如果你可以提前预知接下来将会有多少元素追加到列表中,可以使用该方法避免 QList 内部数组重复分配内存。需要注意的是如果内部数组保存的是元素指针,则仅会仅预分配保存指针的数组的内存。

该方法在 Qt 4.7 中引入。

int QList::size() const

返回列表中元素的个数。

另请参阅 isEmpty() 和 count()。

bool QList::startsWith(const T &value) const

如果列表非空且第一个元素等于 value 则返回 true ,否则返回 false

该方法在 Qt 4.5 中引入。

另请参阅 isEmpty() 和 contains()。

void QList::swap(QList &other)

交换列表 other 和当前列表。该操作非常快且绝对不会失败。

该方法在 Qt 4.8 中引入。

void QList::swapItemsAt(int i, int j)

交换位于索引位置 ij 的元素。该方法会假定 fromto 都不小于 0 且小于 size()。为了避免调用出错,请提前检查 fromto 是否不小于 0 且小于 size()。

示例:

QList<QString> list;
list << "A" << "B" << "C" << "D" << "E" << "F";
list.swapItemsAt(1, 4);
// list: ["A", "E", "C", "D", "B", "F"]

该方法在 Qt 5.13 中引入。

另请参阅 move()。

T QList::takeAt(int i)

移除位于索引位置 i 的元素并返回该元素。 i 必须是列表中合法的索引位置 (即 0 <= i < size())。

如果并不需要返回值,使用 removeAt() 会更高效。

另请参阅 removeAt(), takeFirst() 和 takeLast()。

T QList::takeFirst()

移除列表中第一个元素并返回该元素,等同于 takeAt(0)。该方法会假定列表非空,为了避免调用失败,应提前调用 isEmpty() 进行检查。

如果该列表是非共享的,那么此操作将花费常量时间

如果不需要返回值,使用 removeFirst() 会更高效。

另请参阅 takeLast(), takeAt() 和 removeFirst()。

T QList::takeLast()

移除列表中最后一个元素并返回该元素。等同于 takeAt(size() - 1)。该方法会假定列表非空,为了避免调用失败,应提前调用 isEmpty() 进行检查。

如果该列表是非共享的,那么此操作将花费常量时间

如果不需要返回值,使用 removeLast() 会更高效。

另请参阅 takeFirst(), takeAt() 和 removeLast()。

QSet QList::toSet() const

返回一个包含且仅包含该 QList 中所有数据的 QSet 。由于 QSet 不允许有重复的数据,因此得到的 QSet 中的元素可能会少于原列表。

示例:

QStringList list;
list << "Julia" << "Mike" << "Mike" << "Julia" << "Julia";

QSet<QString> set = list.toSet();
set.contains("Julia");  // 返回 true
set.contains("Mike");   // 返回 true
set.size();             // 返回 2

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 toVector(), fromSet() 和 QSet::fromList()。

std::list QList::toStdList() const

返回一个包含且仅包含该 QList 中所有数据的 std::list。

示例:

QList<double> list;
list << 1.2 << 0.5 << 3.14;

std::list<double> stdlist = list.toStdList();

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 fromStdList() 和 QVector::toStdVector()。

QVector QList::toVector() const

返回一个包含且仅包含该 QList 中所有数据的 QVector 对象。

示例:

QStringList list;
list << "Sven" << "Kim" << "Ola";

QVector<QString> vect = list.toVector();
// vect: ["Sven", "Kim", "Ola"]

注意: 从 Qt 5.14 开始,Qt 泛型容器类支持范围构造函数,建议用来取代这个方法。

另请参阅 toSet(), fromVector() 和 QVector::fromList()。

T QList::value(int i) const

返回位于索引位置 i 的元素的值。

如果索引 i 越界了,该方法会返回一个默认值。如果想确保索引位于边界内,你可以使用 at() 来代替,同时也会略快一些。

另请参阅 at() 和 operator[]()。

T QList::value(int i, const T &defaultValue) const

这是个重载函数。

如果索引 i 越界了,该方法会返回 defaultValue

bool QList::operator!=(const QList &other) const

如果 other 不等于该列表则返回 true,否则返回 false

当且仅当两个列表以相同的顺序包含相同的值时两个列表才被认为是相等的。

该方法要求值类型实现了 operator==()

另请参阅 operator==()。

QList QList::operator+(const QList &other) const

返回一个包含了 other 列表中所有元素附加在该列表之后得到的全部元素的列表。

另请参阅 operator+=()。

QList &QList::operator+=(const QList &other)

other 列表中所有元素追加到当前列表尾部并返回当前列表的引用。

另请参阅 operator+() 和 append()。

QList &QList::operator+=(const T &value)

这是个重载函数。

追加值 value 到列表中。

另请参阅 append() 和 operator<<()。

QList &QList::operator<<(const QList &other)

other 列表中所有元素追加到当前列表尾部并返回当前列表的引用。

另请参阅 operator+=() 和 append()。

QList &QList::operator<<(const T &value)

这是个重载函数。

追加值 value 到列表中。

bool QList::operator==(const QList &other) const

如果 other 等于该列表则返回 true,否则返回 false

当且仅当两个列表以相同的顺序包含相同的值时两个列表才被认为是相等的。

该方法要求值类型实现了 operator==()

另请参阅 operator!=()。

T &QList::operator[](int i)

以可修改的引用返回位于索引位置 i 的元素。i 必须是列表中一个合法的索引位置 (即 0 <= i < size())。

如果对一个处于共享状态的列表调用该方法,则会触发对所有元素的拷贝。否则该方法运行时间开销为常量时间复杂度。如果你不打算修改列表,你用当使用 QList::at()。

另请参阅 at() 和 value()。

const T &QList::operator[](int i) const

这是个重载函数。

等同于 at()。 该方法运行时间开销为 常量时间复杂度

相关非成员函数

template uint qHash(const QList &key, uint seed = 0)

返回一个 key 的哈希值,可通过 seed 设置计算的种子。

该方法要求值类型 T 提供 qHash() 的重载。

该方法在 Qt 5.6 中引入。

template bool operator<(const QList &lhs, const QList &rhs)

如果列表 lhs字典序小于 rhs 则返回 true; 否则返回 false

该方法要求值类型实现了 operator<()

该方法在 Qt 5.6 中引入。

template QDataStream &operator<<(QDataStream &out, const QList &list)

将列表 list 写入流 out 中。

该方法要求值类型实现了 operator<<()

另请参阅 QDataStream 操作符格式

template bool operator<=(const QList &lhs, const QList &rhs)

如果列表 lhs字典序小于或等于 rhs 则返回 true; 否则返回 false

该方法要求值类型实现了 operator<()

该方法在 Qt 5.6 中引入。

template bool operator>(const QList &lhs, const QList &rhs)

如果列表 lhs字典序大于 rhs 则返回 true; 否则返回 false

该方法要求值类型实现了 operator<()

该方法在 Qt 5.6 中引入。

template bool operator>=(const QList &lhs, const QList &rhs)

如果列表 lhs字典序大于或等于 rhs 则返回 true; 否则返回 false

该方法要求值类型实现了 operator<()

该方法在 Qt 5.6 中引入。

template QDataStream &operator>>(QDataStream &in, QList &list)

从流 in 中读取一个列表到 list

该方法要求值类型实现了 operator>>()

另请参阅 QDataStream 操作符格式

已废弃成员

下述的 QList 成员已被废弃。 仅为保证旧代码的正常运行而被保留。我们强烈建议在新代码中不要再使用这些成员。

公共成员函数

(obsolete) voidswap(int i, int j)

成员函数文档

void QList::swap(int i, int j)

此方法已废弃。仅为保证旧代码的正常运行而被保留。我们强烈建议在新代码中不要再使用这些成员。

使用 swapItemsAt() 代替。

另请参阅 move() 和 swapItemsAt().

模型/视图 编程

模型/视图编程简介

Qt 中包含了一系列的项目视图类,他们使用了模型/视图架构来管理数据和显示之间的关系。此架构的功能分离特征给开发人员在自定义项目的呈现形式时带来了很大的灵活性,并提供标准的模型接口,以允许将各种数据源与现有项目视图一起使用。在本文档中,我们对模型/视图进行了简要介绍,概述了所涉及的概念,并描述了项目视图系统的结构特征。介绍了体系结构中的每个组件,并给出了示例,这些示例告诉我们如何使用所提供的类。

模型/视图体系架构

模型-视图-控制器(MVC)是源自 Smalltalk 的设计模式,在构建用户界面时经常使用。在《设计模式》一书中,Gamma 等人写到:

MVC 由三种对象组成。模型是应用程序对象,视图是其在屏幕上的呈现,控制器定义了用户界面对用户输入的反应方式。 在MVC之前,用户界面设计往往会将这些对象整合在一起。 MVC 使它们解耦以增加灵活性和重用性。

如果将视图和控制器对象组合在一起,就是模型/视图架构。基于将数据的存储方式与向用户呈现的方式分开的原理,模型/视图架构提供了一个更简单的框架。这种分离使得可以在几个不同的视图中显示相同的数据,并实现新的视图类型,而无需更改基础数据结构。为了灵活处理用户输入,我们引入了委托的概念。在此框架中使用委托的好处在于,它允许自定义呈现和编辑数据项的方式。

模型/视图架构

模型与数据源通信,为架构中的其他组件提供接口。通信的性质取决于数据源的类型以及模型的实现方式。

视图从模型中获取模型索引; 这些索引是对数据项的引用。 通过向模型提供模型索引,视图可以从数据源检索出数据项。

在标准视图中,委托负责渲染显示数据项。 当编辑项目后,委托将直接通过模型索引与模型进行通信。

通常,模型/视图类可以分为上述三个组:模型,视图和委托。这些组件中的每个组件都由抽象类定义,这些抽象类提供了公共接口,并在某些情况下提供了一些功能的默认实现。抽象类应被子类化,以提供其他组件期望的全部功能;当然也可以编写专用组件。

模型、视图和委托之间通过信号槽通信。

  • 数据源的数据发生改变时模型将发射信号通知视图。
  • 用户交互发生改变时,视图将发射相应的信号。
  • 在编辑期间,委托将发射信号来告知模型和视图有关编辑器的状态。

模型

所有项目模型均基于 QAbstractItemModel 类。此类定义一个接口,视图和委托使用该接口访问数据。数据本身不必存储在模型中。它可以保存在由单独的类,文件,数据库或某些其他应用程序组件提供的数据结构或存储库中。

有关模型的基本概念在 “模型类”部分中介绍。

QAbstractItemModel 提供了一个数据接口,该接口足够灵活,可以处理以表,列表和树的形式表示数据的视图。但是,当为列表和类似表的数据结构实现新模型时,QAbstractListModelQAbstractTableModel 类是更好的选择,因为它们提供了常用功能的默认实现。这些类中的每一个都可以被子类化以提供支持特殊类型的列表和表的模型。

创建新模型 部分中讨论了模型子类化的过程。

Qt提供了一些现成的模型,可用于处理数据项:

如果这些标准模型不满足您的要求,则可以将 QAbstractItemModelQAbstractListModelQAbstractTableModel 子类化以创建您自己的自定义模型。

视图

Qt 提供了针对各种视图的完整实现:QListView 用于显示项目列表,QTableView 用于显示表结构模型的数据,QTreeView 在一个分层次的结构列表中显示数据项。这些类均基于 QAbstractItemView 抽象基类。尽管这些类都是已经实现好的,但也可以将它们子类化以提供满足我们需求的自定义视图。

所有可用的视图可在 视图类 部分中进行查阅。

委托

QAbstractItemDelegate 是模型/视图框架中委托的抽象基类。默认委托实现由 QStyledItemDelegate 提供, Qt 中的标准视图都将其作为默认委托。但是,QStyledItemDelegateQItemDelegate 是绘制和为视图中的项目提供编辑器的独立替代方法。它们之间的区别在于 QStyledItemDelegate 使用当前样式来绘制其项目。因此,在实现自定义委托或使用 Qt 样式表时,建议将 QStyledItemDelegate 用作基类。

委托在 “委托类” 部分中进行了描述。

排序

在模型/视图架构中,有两种方法可以进行排序;选择哪种方法取决于底层使用的模型。

如果您的模型是可排序的,即重新实现 QAbstractItemModel::sort() 函数,则 QTableViewQTreeView 都提供了API,可让您以编程方式对模型数据进行排序。 另外,通过将 QHeaderView::sortIndicatorChanged() 信号连接到 QTableView::sortByColumn() 槽函数或 QTreeView::sortByColumn() 槽函数,可以启用交互式排序(即允许用户通过单击视图的标题对数据进行排序))。

如果您的模型没有所需的接口,或者如果您想使用列表视图来呈现数据,则另一种方法是在视图呈现数据之前,使用委托模型来转换模型的结构。 有关 代理模型 的部分将对此进行详细介绍。

便捷类

从标准视图类派生出了许多便捷类,用于 Qt 中基于项目的项目视图类和表类,它们不打算被子类化。

比如 QListWidgetQTreeWidgetQTableWidget

这些类的灵活性不如视图类,并且不能与任意模型一起使用。我们建议您使用模型/视图方法来处理项目视图中的数据,除非您强烈需要一组基于项目的类。

如果希望在使用基于项目的接口的同时利用模型/视图方法提供的功能,请考虑将视图类(例如 QListViewQTableViewQTreeView )与 QStandardItemModel 一起使用。

使用模型和视图

以下各节说明如何在 Qt 中使用模型/视图模型。每个部分都包含一个示例,紧接着是展示如何创建新组件。

Qt 中包含的两个模型

Qt 提供的两个标准模型是 QStandardItemModelQFileSystemModelQStandardItemModel 是一个多功能模型,可用于表示列表,表和树视图所需的各种不同的数据结构。该模型还保存数据项。QFileSystemModel 是用于维护有关目录内容的信息的模型,它本身不保存任何数据项,而仅表示本地文件系统上的文件和目录。

QFileSystemModel 提供了一个现成的模型用来测试使用,并且可以通过简单的配置就可以使用现有的数据。使用该模型,我们可以展示如何创建一个可用于现成视图的模型,并探索如何使用模型索引来操控数据。

通过现有模型使用视图

QListViewQTreeView 类是最适合与 QFileSystemModel一起使用的视图。下面提供的示例是分别在树形视图和列表视图中显示相同的目录内容。这些视图共享用户的选择,以便在两个视图中突出显示所选的项目。

shared dir model

我们使用了现成的模型 QFileSystemModel,并创建了一些视图来显示目录的内容。展示了使用模型的最简单方法。 该模型的构建和使用是在单个 main() 函数中执行的:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QSplitter *splitter = new QSplitter;

    QFileSystemModel *model = new QFileSystemModel;
    model->setRootPath(QDir::currentPath());

该模型被设置为使用来自特定文件系统的数据。调用 setRootPath() 将告诉模型文件系统上的哪个驱动器会暴露给视图。

我们使用同一个模型创建两个不同的视图,来查看模型中的项目呈现出来的效果:

QTreeView *tree = new QTreeView(splitter);
tree->setModel(model);
tree->setRootIndex(model->index(QDir::currentPath()));

QListView *list = new QListView(splitter);
list->setModel(model);
list->setRootIndex(model->index(QDir::currentPath()));

视图的构造方法与其他部件一样。设置视图来显示模型中的项目仅需使用目录模型作为参数来调用视图的 setModel() 函数即可。我们通过在每个视图上调用 setRootIndex() 函数来过滤模型提供的数据,并从文件系统模型中为当前目录传递合适的模型索引。

这种情况下对于 QFileSystemModel 来说只能通过传递一个目录参数来使用 index() 函数获取索引,模型索引在 模型类 部分中讨论。

该函数的其余部分是在分裂器部件中显示视图,并运行应用程序的事件循环:

    splitter->setWindowTitle("Two views onto the same file system model");
    splitter->show();
    return app.exec();
}

在上面的示例中,我们忽略了如何处理项目选择。 在 处理项目视图中的选择项 部分中将更详细地介绍。

模型类

在学习如何处理选择项之前,理解模型/视图框架中使用的概念是很有用的。

基本概念

在模型/视图体系结构中,模型提供了视图和委托用来访问数据的标准接口。在 Qt 中,标准接口由 QAbstractItemModel 类定义。无论数据项如何存储在任何基础数据结构中,QAbstractItemModel 的所有子类都将数据表示为一个有层次的包含项表的结构。视图使用此约定来访问模型中的数据项,但是它们向用户呈现此信息的方式不受限制。

modelview-models

模型通过信号槽机制通知所有附加视图有关数据更改的信息。

本节描述一些基本概念,这些概念对于其他组件通过模型类访问数据项的方式至关重要。 稍后的部分将讨论更高级的概念。

模型索引

为了确保数据的表示方式与访问方式分开,引入了模型索引的概念。通过模型获得的每条信息都由模型索引表示。视图和委托使用这些索引来请求要显示的数据项。

所以,只有模型需要知道如何获取数据和定义数据类型。模型索引包含一个指向创建它们的模型的指针,以免在使用多个模型时造成混淆。

QAbstractItemModel *model = index.model();

模型索引提供了一个对信息的临时的引用,可用于通过模型检索或修改数据。由于模型可能会不时重组其内部结构,因此模型索引可能会变得无效,不应进行存储。如果需要长期使用一条信息,则必须创建一个持久的模型索引。这为模型保持最新状态提供了参考。临时模型索引由 QModelIndex 类提供,而持久模型索引由 QPersistentModelIndex 类提供。

要获得与数据项相对应的模型索引,必须为模型指定三个属性:行号,列号和父项的模型索引。以下各节将详细描述和解释这些属性。

行和列

在基本的形式中,可以将模型作为一个简单的表进行访问,项目按行和列的编号位于其中。这并不意味着底层数据存储在数组结构中;行号和列号的使用仅仅是组件之间相互通信的约定。我们可以通过在模型中指定给定项目的行号和列号来检索有关任何给定项目的信息,我们接收到的是代表该项目的索引:

QModelIndex index = model->index(row, column, ...);

为简单的单层数据结构(例如列表和表)提供接口的模型不需要提供任何其他信息,但是,如上述代码所示,在获取模型索引时,我们需要提供更多信息。

行和列

该图显示了基本表模型的表示形式,其中每个项目都由一对行号和列号定位。通过将相关的行号和列号传递给模型,我们获得了一个引用数据项的模型索引。

QModelIndex indexA = model->index(0, 0, QModelIndex());
QModelIndex indexB = model->index(1, 1, QModelIndex());
QModelIndex indexC = model->index(2, 1, QModelIndex());

始终通过用 QModelIndex() 指定为其父项来引用模型中的顶级项目。下一节将对此进行讨论。

项的父项

当在表视图或列表视图中使用数据时,模型提供的类似于表的接口就非常合适。行号和列号系统准确地映射到视图显示项目的方式上。但是,诸如树状视图的结构对于模型项目的操作要求模型提供更灵活的接口。每个项目也可以是另一个项目表的父项,就像树状视图中的顶级项目可以包含另一个项目列表一样。

当请求模型项的索引时,我们必须提供有关该项父项的一些信息。在模型之外,引用项目的唯一方法是通过模型索引,因此还必须提供父模型索引:

QModelIndex index = model->index(row, column, parent);
父项、行和列

该图展示了树模型的表示形式,其中每一项均由父项、行号和列号检索出来。

“A”和“C”项在模型中为同级顶级:

QModelIndex indexA = model->index(0, 0, QModelIndex());
QModelIndex indexC = model->index(2, 1, QModelIndex());

“A”项有多个子项。使用以下代码获得“B”项的模型索引:

QModelIndex indexB = model->index(1, 0, indexA);

项角色

模型中的项可以为其他组件扮演各种不同的角色,从而可以为不同的数据提供不同的方案。 例如,Qt::DisplayRole 用于访问可以在视图中显示为文本的字符串。通常,项包含许多不同角色的数据,标准角色由 Qt::ItemDataRole 定义。

我们可以通过向模型传递与该项相对应的模型索引,并指定一个角色来获取所需的数据类型,从而获得我们想要的数据:

QVariant value = model->data(index, role);
项角色

项角色向模型指示要引用的数据类型。视图可以以不同的方式显示角色,因此为每个角色提供适当的信息很重要。

创建新模型 部分将更详细地介绍角色的某些特定用法。

项标准角色 Qt::ItemDataRole 涵盖了大部分常用的项角色。通过为每个角色提供适当的项目数据,模型可以向视图和委托提示如何将项呈现给用户。不同类型的视图可以根据自身需要解释或忽略此信息。也可以为特定目的定义其他角色。

摘要

  • 模型索引以独立于任何底层数据结构的方式提供给视图和委托有关模型所提供项的位置的信息。
  • 项通过其行号和列号以及其父项的模型索引检索出来。
  • 模型索引是由模型根据其他组件(例如视图和委托)的请求构造出来的。
  • 如果使用 index() 请求索引时为父项指定了有效的模型索引,则返回的索引将引用模型中该父项之下的项。获得的索引指向该项目的子项。
  • 如果使用 index() 请求索引时为父项指定了无效的模型索引,则返回的索引引用模型中的顶级项。
  • 项角色 用来区分与项关联的不同类型的数据。

使用模型索引

为了演示如何使用模型索引从模型中检索数据,我们设置了一个没有视图的 QFileSystemModel,并在部件中显示文件和目录的名称。尽管这没有展示使用模型的正常方法,但是它说明了在处理模型索引时模型使用的规则。

QFileSystemModel 加载是异步的,以最大程度地减少系统资源的使用。在处理此模型时,我们必须考虑到这一点。

我们通过以下方式构造文件系统模型:

QFileSystemModel *model = new QFileSystemModel;
connect(model, &QFileSystemModel::directoryLoaded, [model](const QString &directory) {
    QModelIndex parentIndex = model->index(directory);
    int numRows = model->rowCount(parentIndex);
});
model->setRootPath(QDir::currentPath);

在这种情况下,我们首先设置默认的 QFileSystemModel 。我们将其连接到 lambda,在其中我们将使用该模型提供的 index() 的特定实现来获取父索引。 在 lambda 中,我们使用 rowCount() 函数计算模型中的行数。最后,我们设 QFileSystemModel 的根路径,以便它开始加载数据并触发 lambda

为简单起见,我们只处理模型第一栏中的项目。我们依次检查每一行,获取每一行中第一项的模型索引,然后读取模型中为该项存储的数据。

for (int row = 0; row < numRows; ++row) {
    QModelIndex index = model->index(row, 0, parentIndex);

为了获得模型索引,我们指定行号,列号(第一列为零),并为所需的所有项的父项指定适当的模型索引。使用模型的 data() 函数检索存储在每个项目中的文本。我们指定模型索引和 DisplayRole 获取字符串形式的项数据。

QString text = model->data(index, Qt::DisplayRole).toString();
    // Display the text in a widget.

}

以上示例演示了从模型中检索数据的基本用法:

  • 模型的大小范围可以使用 rowCount()columnCount 获取到。这些函数通常需要指定一个父项模型索引。
  • 模型索引用于访问模型中的数据项。指定一个项需要行、列和父项的模型索引。
  • 通过 QModelIndex() 指定一个空的父项的索引来访问模型中的顶层项。
  • 项包含不同角色的数据。要获得特定角色的数据,必须同时向模型提供模型索引和角色。

拓展阅读

可以通过提供了标准接口的 QAbstractItemModel 类来创建新模型。在 创建新模型 部分,我们将通过创建一个方便可用的保存字符串列表的模型来展示这一点。

视图类

概念

在模型/视图架构中,视图从模型中获取数据项并将其呈现给用户。呈现数据的方式不必类似于模型提供数据的方式,而可以与用于存储数据项的底层数据结构完全不同

通过使用 QAbstractItemModel 提供的标准模型接口,QAbstractItemView 提供的标准视图接口以及使用表示数据项的模型索引来实现内容和表示的分离。视图通常管理从模型获得的数据的整体布局。它们可以自己呈现单个数据项,或使用委托来处理渲染和编辑功能。

除了显示数据外,视图还处理项目之间的导航以及项目选择。这些视图还实现了基本的用户界面功能,例如上下文菜单和拖放功能。视图可以提供项目的默认编辑功能,也可以与 委托 一起使用以提供自定义编辑器。

可以在没有模型的情况下构造视图,但是必须提供模型才能显示有用的信息。视图通过使用 选择项 来跟踪用户选择的项目,这些选择项可以被每个视图单独维护,或者在多个视图之间共享。

一些视图,例如 QTableViewQTreeView,需要显示表头和项目。这些由视图类 QHeaderView 实现。表头通常与包含它们的视图访问的是同一个模型。他们使用 QAbstractItemModel::headerData() 函数从模型中检索数据,并且通常以标签形式显示表头信息。可以继承 QHeaderView 类实现新的标头,以为视图提供更专业的标签。

使用现有视图

Qt提供了三种现成的视图类,它们以大多数用户熟悉的方式显示来自模型的数据。 QListView 可以将模型中的项目显示为简单列表或经典图标视图的形式。QTreeView 将模型中的项目显示为具有层次结构的列表,从而以紧凑的方式表示深层嵌套的结构。QTableView 以表格的形式显示来自模型的项目,非常类似于电子表格应用程序的布局。

standard-views

上面显示的标准视图的默认行为对于大多数应用程序来说应该足够了。它们提供了基本的编辑功能,并且可以进行定制以满足更专业的用户界面的需求。

使用模型

我们以创建的字符串列表模型为例,设置一些数据,并构造一个视图以显示模型的内容。所有这些都可以在一个函数中执行:

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

    // Unindented for quoting purposes:
    QStringList numbers;
    numbers << "One" << "Two" << "Three" << "Four" << "Five";

    QAbstractItemModel *model = new StringListModel(numbers);

请注意,StringListModel 被声明为 QAbstractItemModel。这使我们能够使用模型的抽象接口,并确保即使我们将字符串列表模型替换为其他模型,代码仍然可以正常工作。

QListView 提供的列表视图足以在字符串列表模型中显示项目。我们构造视图,并使用以下代码行建立模型:

    QListView *view = new QListView;
    view->setModel(model);

该视图以正常方式显示:

    view->show();
    return app.exec();
}

视图渲染显示模型中的内容,并通过模型的接口访问数据。当用户尝试编辑项目时,视图使用默认委托提供一个默认的编辑器部件。

stringlistmodel

上图显示了 QListView 如何显示字符串列表模型中的数据。由于模型是可编辑的,因此视图允许使用默认委托来编辑列表中的每个项目。

多个视图共用一个模型

为同一模型提供多个视图仅是为每个视图设置相同模型的问题。在下面的代码中,我们创建了两个表视图,每个表视图都使用了创建的简单的表模型:

    QTableView *firstTableView = new QTableView;
    QTableView *secondTableView = new QTableView;

    firstTableView->setModel(model);
    secondTableView->setModel(model);

在模型/视图架构中使用信号槽可以将对模型的更改传递给到所有设置该模型的视图,从而确保我们始终可以访问相同的数据,而不管所使用的视图如何。

sharedmodel-tableviews

上面的两张图片显示了两种不同的视图使用同一个模型的情况,每一个视图都包含一些被选中的项。尽管在视图中始终显示来自模型的数据,但每个视图都维护一个自己内部的选择模型。在某些情况下这可能很有用,但是对于许多应用程序来说,需要一个共享的选择模型。

处理项目选择

QItemSelectionModel 类提供了用于处理视图中项目选择的机制。默认情况下,所有标准视图都构建自己的选择模型,并以常规方式与其交互。可以通过 selectionModel() 函数获得视图使用的选择模型,并可以使用 setSelectionModel 指定替换选择模型。当我们想在同一模型数据上提供多个一致的视图时,控制视图使用的选择模型的功能非常有用。

通常,除非要对模型或视图进行子类化,否则无需直接操作选择的内容。但是,如果需要,可以访问选择模型的接口,这在 处理项目视图中的选择项 部分中进行了探讨。

在视图之间共享选择

尽管默认情况下视图类提供它们自己的选择模型很方便,但是当我们在同一个模型上使用多个视图时,通常希望在所有视图中都同时显示模型的数据和用户的选择。由于视图类允许替换其内部选择模型,因此我们可以使用以下代码在视图之间实现统一选择:

    secondTableView->setSelectionModel(firstTableView->selectionModel());

为第二个视图提供了第一个视图的选择模型。现在,两个视图都在相同的选择模型上运行,从而使数据和所选项目保持同步。

sharedselection-tableviews

在上面显示的示例中,使用了两个相同类型的视图来显示相同模型的数据。但是,如果使用两种不同类型的视图,则在每个视图中所选项目的表现方式可能会非常不同。例如,表视图中的连续选择在树状图视图中就表现为一系列分散的高亮项的片段。

委托类

概念

与“模型-视图-控制器”模式不同,模型/视图设计不包括用于管理与用户交互的完全独立的组件。通常,视图负责将模型数据呈现给用户,并负责处理用户输入。为了使获取此输入的方式具有一定的灵活性,交互由委托执行。这些组件提供输入功能,还负责在某些视图中渲染单个项目。在 QAbstractItemDelegate 类中定义了用于控制委托的标准接口。

委托应该能够通过实现 paint()sizeHint() 函数来呈现它们自己的内容。但是,基于简单窗口部件的委托可以继承 QStyledItemDelegate 而不是 QAbstractItemDelegate 类,并使用这些函数的默认实现。

委托编辑器可以通过使用部件来管理编辑过程或直接处理事件来实现。本节稍后将介绍第一种方法,在 SpinBox委托 示例中也有相应的实现。

Pixelator 示例显示了如何创建自定义委托来专门渲染一个表视图。

使用现有的委托

Qt 提供的标准视图使用 QStyledItemDelegate 实例提供编辑功能。委托接口的默认实现以通用的样式为每个标准视图 QListViewQTableViewQTreeView 呈现项目。

所有标准角色均由标准视图使用的默认委托处理。QStyledItemDelegate 文档中描述了这些解释的方式。

视图使用的委托由 itemDelegate() 函数返回。setItemDelegate() 函数允许为标准视图设置自定义委托,并且在为自定义视图设置委托时必须使用此函数。

一个简单的委托

此处实现的委托使用 QSpinBox 提供编辑功能,并且主要用于显示整数的模型。因此我们建立了一个基于整数的自定义的表模型,但是由于自定义委托控制数据输入,因此我们可以轻松地使用 QStandardItemModel。 我们构造一个表视图来显示模型的内容,使用自定义委托进行编辑。

spinboxdelegate-example

我们从 QStyledItemDelegate 继承实现自定义委托,因为我们不想编写自定义显示函数。但是,我们仍然必须提供函数来管理编辑器部件:

class SpinBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    SpinBoxDelegate(QObject *parent = nullptr);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override;

    void setEditorData(QWidget *editor, const QModelIndex &index) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const override;

    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const override;
};

注意,在构造委托时,不会设置任何编辑器部件。我们仅在需要时构造一个编辑器部件。

提供一个编辑器

在此示例中,当表视图需要提供编辑器时,要求委托提供适合于项目修改的编辑器部件。createEditor() 函数可以让委托能够设置合适的部件作为编辑器:

QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem &/* option */,
                                       const QModelIndex &/* index */) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setMaximum(100);

    return editor;
}

注意,我们不需要保留指向编辑器部件的指针,因为当视图不再需要该编辑器时,负责将其销毁。

我们在编辑器上安装了委托的默认事件过滤器,以确保它提供用户期望的标准编辑快捷方式。可以将其他快捷方式添加到编辑器中,以允许更复杂的行为。这些内容将在 编辑提示 部分中进行讨论。

视图可通过调用稍后我们定义的函数来确保正确设置编辑器的数据和几何形状。我们可以根据视图提供的模型索引创建不同的编辑器。例如,如果我们有一列整数和一列字符串,则可以返回 QSpinBoxQLineEdit,具体取决于正在编辑的列。

委托必须提供将模型数据复制到编辑器中的功能。在此示例中,我们读取了 显示角色 中存储的数据,并在 spin box 中相应地设置了值。

void SpinBoxDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->setValue(value);
}

在此示例中,我们知道编辑器部件是一个 spin box,但是我们可以为模型中的不同类型的数据提供不同的编辑器,在这种情况下,我们需要在访问其成员函数之前将部件转换为适当的类型。

提交数据到模型

当用户完成在 spin box 中的值编辑后,视图通过调用 setModelData() 函数要求委托将已编辑的值存储在模型中。

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();

    model->setData(index, value, Qt::EditRole);
}

由于视图管理委托的编辑器部件,因此我们只需要使用提供的编辑器的内容来更新模型。在这种情况下,我们确保 spin box 是最新的,并使用指定的索引更新模型数据。

标准 QStyledItemDelegate 类在完成编辑后通过发出 closeEditor() 信号通知视图。该视图确保编辑器部件已关闭并销毁。在此示例中,我们仅提供简单的编辑工具,因此我们永远不需要发出此信号。

数据的所有操作都是通过 QAbstractItemModel 提供的接口执行的。这使委托在很大程度上不受其处理的数据类型的影响,但是必须做出一些假设才能使用某些类型的编辑器部件。在此示例中,我们假定模型始终包含整数值,但是我们仍然可以将此委托与其他类型的模型一起使用,因为 QVariant 为意外的数据提供了合理的默认值。

更新编辑器的几何图形

委托负责管理编辑器的几何图形。创建编辑器时以及更改项目的大小或在视图中的位置时,必须设置几何形状。幸运的是,视图在 视图选项 对象内提供了所有必要的几何信息。

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
                                           const QStyleOptionViewItem &option,
                                           const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

在这种情况下,我们仅使用了视图选项提供的项的矩形几何信息。具有多个元素的项目的委托将不会直接使用项目矩形几何信息。它将编辑器放置在相对于其它项的位置。

编辑提示

编辑后,委托应向其他组件提供有关编辑过程结果的提示,并提供有助于后续任何编辑操作的提示。这是通过发出一个带有适当提示的 closeEditor() 信号来实现的。 默认情况下,这是由我们在构造 spin box 时安装的 QStyledItemDelegate 事件过滤器来处理的。

spin box 的行为可以进行调整,以使其更加用户友好。在 QStyledItemDelegate 提供的默认事件过滤器中,如果用户单击 Return 确认在 spin box 中的选择,则委托将值提交给模型并关闭 spin box 。我们可以通过在 spin box 上安装我们自己的事件过滤器来更改此行为,并提供我们需要的编辑提示。例如,我们可以发出带有 EditNextItem 提示的 closeEditor() 信号来自动开始编辑视图中的下一个项目。

另一种不需要使用事件过滤器的方法是提供我们自己的编辑器部件,为方便起见,可能将 QSpinBox 子类化。这种替代方法可以使我们更好地控制编辑器部件的行为,而无需编写其他代码。如果需要自定义标准 Qt 编辑器窗口部件的行为,简单常用的方法就是在委托中安装事件过滤器。

委托不必发出这些提示,但是为了应用程序的更加可用,我们需要发出提示以支持常见编辑操作。

处理项目视图中的选择项

概念

项目视图类中使用的选择模型对基于模型/视图架构的选择提供了的一般描述。尽管用于提供选择的标准视图足以处理提供的项目视图,但是选择模型允许创建专门的选择模型,以适合项目模型和视图的要求。

视图中被选择的项目的信息存储在一个 QItemSelectionModel 类的实例中。它负责维护单个模型中项目的模型索引,并且独立于任何视图。由于模型上可以有很多视图,因此可以在视图之间共享选择,从而允许应用程序以一致的方式显示多个视图。

选择由选择范围指定。只需记录每一个选择范围开始和结束的模型索引即可,这些有效地维护了有关大量项目选择的信息。非连续的选择可以使用多个选择范围来描述。

选择可以看作是在选择模型中保存的一个模型索引集合,最近的项目选择被称为当前选择。即使在应用了某些类型的选择命令后,也可以修改此选择的效果。这些将在本节后面讨论。

当前项和选择项

视图中总有一个当前项目和一个被选择的项目,两者时两个独立的状态。在同一时间,一个项目既可以是当前项目也同时可以是被选择的项目。视图图则确保总是有一个项目作为当前项目来实现键盘导航。

下表显示了当前项目和被选择的项目的区别。

当前项选择项
只能有一个当前项目可以有多个被选择的项目
使用键盘导航键或者鼠标按键可以改变当前项目项目是否处于被选择状态,取决于用户交互时当前几个预定义好的模式,比如单项选择、多重选择等
如果按下 F2 键或者双击都可以编辑当前项目(前提是允许编辑)当前项目可以指定一个范围来一起选择或者取消选择(或者两种混用)
当前项目会显示焦点矩形被选择的项目会使用选择矩形来表示

当操作选择时,可以将 QItemSelectionModel 看作是一个项目模型中所有项目的选择状态的一个记录。一旦设置了一个选择模型,所有的集合项目都可以被选择、取消选择或者切换选择状态,而不需要知道哪一个项目已经被选择了。所有被选择的项目的索引都可以被随时进行检索,其他的组件也可以通过信号槽机制来获取选择模型的改变信息。

使用选择模型

标准的视图类中提供了默认的选择模型,可以在大多数的应用中直接使用。属于一个视图的选择模型可以使用这个视图的 setSelectionModel() 获得,而且还可以在多个视图之间使用 setSelectionModel() 函数来共享该选择模型,所以一般是不需要重新构建一个选择模型的。

通过指定一个模型和一对指向 QItemSelection 的模型索引来创建选择。使用索引来引用给定模型中的项目,并将它们解释为所选项目块中的左上和右下项目。要将选择应用于模型中的项目,需要将选择提交给选择模型。这可以通过多种方式来实现,每种方式都对选择模型中已经存在的选择产生不同的影响。

选择项目

为了演示选择的一些主要功能,我们构造了一个总共有32个项目的自定义表格模型实例,并将其设置给表格视图:

   TableModel *model = new TableModel(8, 4, &app);

   QTableView *table = new QTableView(0);
   table->setModel(model);

   QItemSelectionModel *selectionModel = table->selectionModel();

检索表视图的默认选择模型以供以后使用。我们不修改模型中的任何项目,而是选择一些显示在表左上方的一些项目。为此,我们需要检索与要选择的区域中的左上和右下项目相对应的模型索引:

   QModelIndex topLeft;
   QModelIndex bottomRight;

   topLeft = model->index(0, 0, QModelIndex());
   bottomRight = model->index(5, 2, QModelIndex());

要在模型中选择这些项目,并在表视图中查看相应的更改,我们需要构造一个选择对象,然后将其应用于选择模型:

   QItemSelection selection(topLeft, bottomRight);
   selectionModel->select(selection, QItemSelectionModel::Select);

使用 选择标志 的组合定义的命令将选择应用于选择模型。在这种情况下,所使用的标志使得记录在选择对象中的项目被包括在选择模型中,而与它们先前的状态无关。视图显示结果选择。

selected-items1

在示例模型上执行的命令都涉及到累积模型中各项的选择。也可以清除选择,或用新选择替换当前选择。

要将当前选择替换为新选择,请将其他选择标志与 当前 标志组合。使用此标志的命令指示选择模型将其当前模型索引集合替换为对 select() 的调用中指定的模型索引集合。要在开始添加新选择之前清除所有选择,将其他选择标记与 清除 标记结合使用。它的作用是重置选择模型的模型索引集合。

选择模型中的所有项目

要选择模型中的所有项目,必须为模型的每个级别创建一个选择,以覆盖该级别中的所有项目。为此,我们使用给定的父索引检索与左上和右下项目相对应的索引:

    QModelIndex topLeft = model->index(0, 0, parent);
    QModelIndex bottomRight = model->index(model->rowCount(parent)-1,
       model->columnCount(parent)-1, parent);

使用这些索引和模型构建选择。然后在选择模型中选择相应的项目:

    QItemSelection selection(topLeft, bottomRight);
    selectionModel->select(selection, QItemSelectionModel::Select);

需要对模型中的所有级别执行此操作。对于顶级项目,通常将以定义父索引的方式:

    QModelIndex parent = QModelIndex();

对于分层模型,hasChildren() 函数用于确定任何给定项目是否是另一级别项目的父项。

创建新模型

使用了模型/视图架构的组件之间功能分离特征允许创建的模型使用已有的视图。这种方法可以用标准图形界面组件呈现各种各样的数据源,比如 QListViewQTableViewQTreeView

QAbstractItemModel 类提供了足够灵活的接口,以支持按层次结构排列信息的数据源,从而允许以某种方式插入,删除,修改或分类数据。它还支持拖放操作。

QAbstractListModelQAbstractTableModel 类为更简单的非分层数据结构提供接口支持,并且更易于用作简单列表和表模型。

在本节中,我们将创建一个简单的只读模型,以探索模型/视图架构的基本原理。在本节的稍后部分,我们将修改此简单模型,以便用户可以修改项目。

有关更复杂的模型的示例,请参见 简单树模型 示例。

有关 QAbstractItemModel 子类的要求在 模型子类参考 文档中有更详细的描述。

设计模型

当为已有的数据结构创建新的模型时,考虑需要创建哪种模型很重要的。如果数据结构可以用列表或者表呈现出来,可以子类化 QAbstractListModel 或者 QAbstractTableModel,因为这些类已经为很多功能提供了默认的实现。

如果底层数据结构只能被具体有层次的树形结构表现出来,那么子类化 QAbstractItemModel 就很有必要。在 简单树模型 一例中采用了这种方法。

本节我们实现一个基于字符串列表的 QAbstractListModel 作为基类的简单模型。

无论底层数据结构采用什么形式,通常最好在专用模型中扩展补充标准 QAbstractItemModel API,可以更自然地访问底层数据结构。这样可以更轻松地用数据填充模型,也仍然允许其他常规模型/视图组件使用标准 API 与之交互。下述模型为此提供了一个自定义构造函数。

只读的示例模型

这里我们基于标准 QStringListModel 类实现了一个简单的,非层次结构的只读的数据模型。使用 QStringList 作为其内部数据源,并且仅实现构建功能模型所需的内容。为了简化实现,我们将 QAbstractListModel 子类化,因为它为列表模型定义了明智的默认行为,并且它公开了比 QAbstractItemModel 类更简单的接口。

在实现模型时,重要的是要记住 QAbstractItemModel 本身并不存储任何数据,它只是提供了一个视图用来访问数据的接口。对于最小的只读模型,仅需要实现一些功能,因为大多数接口都有默认实现。 类声明如下:

class StringListModel : public QAbstractListModel
{
    Q_OBJECT

public:
    StringListModel(const QStringList &strings, QObject *parent = nullptr)
        : QAbstractListModel(parent), stringList(strings) {}

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const override;

private:
    QStringList stringList;
};

除了模型的构造函数之外,我们只需要实现两个函数:rowCount() 返回模型中的行数,data() 返回与指定模型索引相对应的数据项。

比较好的模型还实现了 [headerData()],用来显示树形视图和表视图的标题。

请注意,这是一个非分层模型,因此我们不必担心父子关系。如果我们的模型是分层的,那么我们还必须实现 index()parent() 函数。

字符串列表被存储在 stringList 内部的私有成员变量中。

模型尺寸

我们希望模型中的行数与字符串列表中的字符串数相同。考虑到这一点,我们实现 rowCount() 函数:

int StringListModel::rowCount(const QModelIndex &parent) const
{
    return stringList.count();
}

由于模型是非分层的,因此我们可以安全地忽略与父项相对应的模型索引。默认情况下,从 QAbstractListModel 派生的模型仅包含一列,因此我们无需重新实现 columnCount() 函数。

模型标题和数据

对于视图中的项目,我们想返回字符串列表中的字符串。data() 函数负责返回与 index 参数对应的数据项:

QVariant StringListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() >= stringList.size())
        return QVariant();

    if (role == Qt::DisplayRole)
        return stringList.at(index.row());
    else
        return QVariant();
}

仅当提供的模型索引有效,行号在字符串列表中的项目范围内并且请求的角色是我们支持的角色时,我们才返回有效的 QVariant

一些视图(例如 QTreeViewQTableView )能够通过项目数据显示标题。如果我们的模型显示在带有标题的视图中,我们希望标题显示行号和列号。我们可以通过将 headerData() 函数子类化来提供有关标题的信息:

QVariant StringListModel::headerData(int section, Qt::Orientation orientation,
                                     int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
        return QStringLiteral("Column %1").arg(section);
    else
        return QStringLiteral("Row %1").arg(section);
}

同样,仅当角色是我们支持的角色时,我们才返回有效的 QVariant。标题的方向也会影响返回的数据。

并非所有视图都显示带有项目数据的标题,可以通过配置隐藏它们。尽管如此,还是建议实现 headerData() 函数以提供有关模型据的相关信息。

一个项目可以具有多个角色,根据指定的角色给出不同的数据。我们模型中的项目只有一个角色 DisplayRole,因此无论指定的角色如何,我们都将返回项目的数据。但是,我们可以在其他角色中重用为 DisplayRole 提供的数据,例如 ToolTipRole,视图可用来在工具提示中显示有关项目的信息。

可编辑的模型

只读模型显示了如何将简单的选择呈现给用户,但是对于许多应用程序而言,可编辑列表模型更加有用。我们可以通过更改为只读实现的 data() 函数以及实现两个额外的函数 flags()setData() 来修改只读模型,以使项目可编辑。将以下函数声明添加到类定义中:

    Qt::ItemFlags flags(const QModelIndex &index) const override;
    bool setData(const QModelIndex &index, const QVariant &value,
                 int role = Qt::EditRole) override;

让模型可编辑

创建编辑器之前委托将检擦项目是否可编辑。模型必须让委托知道它的一些项目是可编辑的。具体做法是为模型中的每个项返回正确的标志;这种情况下,我们可以使能所有的项目并让这些项目可选择和可编辑:

Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::ItemIsEnabled;

    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

请注意,我们不必知道委托是如何执行实际的编辑过程的。我们只需要为委托提供一种在模型中设置数据的方法。这是通过 setData() 函数实现的:

bool StringListModel::setData(const QModelIndex &index,
                              const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {

        stringList.replace(index.row(), value.toString());
        emit dataChanged(index, index, {role});
        return true;
    }
    return false;
}

在此模型中,字符串列表中与模型索引对应的项目将替换为所提供的值。但是,在修改字符串列表之前,我们必须确保索引有效,项目类型正确并且支持该角色。按照惯例,我们使用 EditRole 角色,因为这是标准项目委托使用的角色。但是,对于布尔值,可以使用 Qt::CheckStateRole 并设置 Qt::ItemIsUserCheckable 标志;然后将使用一个复选框来编辑值。模型中的底层数据对于所有角色都是相同的,这使得该模型与标准组件的集成更加容易。

设置数据后,模型必须让视图知道某些数据已更改。这是通过发出 dataChanged() 信号完成的。由于仅一项数据已更改,因此信号中指定的项范围仅限于一个模型索引。

同样,测试Qt::EditRole 需要更改 data() 函数:

QVariant StringListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() >= stringList.size())
        return QVariant();

    if (role == Qt::DisplayRole || role == Qt::EditRole)
        return stringList.at(index.row());
    else
        return QVariant();
}

插入和删除行

模型中的行数和列数是可以改变的。在字符串列表模型中,仅更改行数才有意义,因此我们仅重新实现用于插入和删除行的函数。这些在类定义中声明:

    bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;

由于此模型中的行与列表中的字符串相对应,所以 insertRows() 函数将多个空字符串插入到字符串列表中的指定位置之前。插入的字符串数等于指定的行数。

父索引通常用于确定插入到模型中的的位置。我们只有一个顶级字符串列表,因此我们只需在该列表中插入空字符串即可。

bool StringListModel::insertRows(int position, int rows, const QModelIndex &parent)
{
    beginInsertRows(QModelIndex(), position, position+rows-1);

    for (int row = 0; row < rows; ++row) {
        stringList.insert(position, "");
    }

    endInsertRows();
    return true;
}

该模型首先调用 beginInsertRows() 函数以通知其他组件行数即将更改。该函数指定要插入的第一行和最后一行新行的行号,以及其父项的模型索引。更改字符串列表后,它将调用 endInsertRows() 以完成操作并通知其他组件该模型的尺寸已更改,并返回 true 表示成功。

从模型中删除行的函数也很简单。要从模型中删除的行由位置和给定的行数指定。我们忽略父索引以简化实现,只是从字符串列表中删除相应的项。

bool StringListModel::removeRows(int position, int rows, const QModelIndex &parent)
{
    beginRemoveRows(QModelIndex(), position, position+rows-1);

    for (int row = 0; row < rows; ++row) {
        stringList.removeAt(position);
    }

    endRemoveRows();
    return true;
}

在删除任何底层数据之前都要调用 beginRemoveRows() 函数,并指定要删除的第一行和最后一行。这允许其他组件在数据不可用之前访问数据。删除行之后,模型将发出 endRemoveRows() 信号以完成操作,并让其他组件知道模型的尺寸已更改。

下一步

我们可以使用 QListView 类显示此模型或任何其他模型提供的数据,以垂直列表的形式显示模型的项目。对于字符串列表模型,此视图还提供了默认编辑器,以便可以操作项目。在 视图类 部分我们研究了标准视图的各种各样的用法。

模型子类参考 文档更详细地讨论了 QAbstractItemModel 子类的要求,并说明了如何在不同类型的模型中实现虚函数来实现各种不同的功能。

项目视图中的便捷类

基于项目的窗口部件具有反映其用途的名称:QListWidget 提供项目列表,QTreeWidget 显示多级树结构,QTableWidget 提供以项目为单位的表格。每个类都继承了 QAbstractItemView 类的行为,该类实现了项目选择和标头管理的常见行为。

列表部件

通常使用 QListWidget 和许多 QListWidgetItems 显示单级列表的项目。列表部件的构造方式与其他部件相同:

    QListWidget *listWidget = new QListWidget(this);

构造列表项时,可以将它们直接添加到列表部件中:

    new QListWidgetItem(tr("Sycamore"), listWidget);
    new QListWidgetItem(tr("Chestnut"), listWidget);
    new QListWidgetItem(tr("Mahogany"), listWidget);

也可以在没有父列表部件的情况下构造它们,并在以后将其添加到列表中:

    QListWidgetItem *newItem = new QListWidgetItem;
    newItem->setText(itemText);
    listWidget->insertItem(row, newItem);

列表中的每个项目都可以显示一个文本标签和一个图标,文本的字体和颜色都可以自定义。工具提示、状态提示和 What's This? 提示也都可以设置。

    newItem->setToolTip(toolTipText);
    newItem->setStatusTip(toolTipText);
    newItem->setWhatsThis(whatsThisText);

默认情况下,列表中的项目会根据添加的顺序显示,也可以使用 Qt::SortOrder 对项目列表进行正向或反向字母顺序排序:

    listWidget->sortItems(Qt::AscendingOrder);
    listWidget->sortItems(Qt::DescendingOrder);

树形部件

QTreeWidgetQTreeWidgetItem 类提供树或项目的层次结构列表。树部件中的每个项目都可以拥有自己的子项目,并且可以显示多列信息。树部件的创建与其他任何部件一样:

    QTreeWidget *treeWidget = new QTreeWidget(this);

在将项目添加到树部件之前,必须设置列数。例如,我们可以定义两列,并创建一个标题以在每列的顶部提供标签:

    treeWidget->setColumnCount(2);
    QStringList headers;
    headers << tr("Subject") << tr("Default");
    treeWidget->setHeaderLabels(headers);

为每个部分设置标签的最简单方法是提供一个字符串列表。对于更复杂的标题,可以构造一个树项目,根据需要对其进行装饰,并将其用作树部件的标题。

树部件中的顶级项目是使用树部件作为其父小部件构造的。可以按任意顺序插入它们,也可以通过在构造每个项目时指定上一个项目来确保以特定顺序列出它们:

    QTreeWidgetItem *cities = new QTreeWidgetItem(treeWidget);
    cities->setText(0, tr("Cities"));
    QTreeWidgetItem *osloItem = new QTreeWidgetItem(cities);
    osloItem->setText(0, tr("Oslo"));
    osloItem->setText(1, tr("Yes"));

    QTreeWidgetItem *planets = new QTreeWidgetItem(treeWidget, cities);

树部件在处理顶级项目时,与树中较深处的其他项目略有不同。可以通过调用树部件的 takeTopLevelItem() 函数从树的顶层删除项目,但可以通过调用其父项的 takeChild() 函数从较低级别的项目中删除项目。使用 insertTopLevelItem() 函数将项目插入树的顶层。在树的较低级别位置,使用父项的 insertChild() 函数。

在树的最高层和最低层之间移动项目很容易。我们只需要检查项目是否为顶级项目,该信息由每个项目的 parent() 函数提供。例如,我们可以删除树部件中的当前项目,而不管其位置如何:

    QTreeWidgetItem *parent = currentItem->parent();
    int index;

    if (parent) {
        index = parent->indexOfChild(treeWidget->currentItem());
        delete parent->takeChild(index);
    } else {
        index = treeWidget->indexOfTopLevelItem(treeWidget->currentItem());
        delete treeWidget->takeTopLevelItem(index);
    }

将项目插入到树部件中的其他位置也遵循相同的模式:

    QTreeWidgetItem *parent = currentItem->parent();
    QTreeWidgetItem *newItem;
    if (parent)
        newItem = new QTreeWidgetItem(parent, treeWidget->currentItem());
    else
        newItem = new QTreeWidgetItem(treeWidget, treeWidget->currentItem());

表部件

使用 QTableWidgetQTableWidgetItem 构造类似于电子表格的项目的表。这些提供了带有标题和要可以滚动的表的窗口部件。

可以创建具有一定数量的行和列的表,也可以根据需要将它们添加到未调整大小的表中。

    QTableWidget *tableWidget;
    tableWidget = new QTableWidget(12, 3, this);

在将表项添加到表中所需位置之前,先在表外部构造它们:

    QTableWidgetItem *newItem = new QTableWidgetItem(tr("%1").arg(
        pow(row, column+1)));
    tableWidget->setItem(row, column, newItem);

通过在表外部构造项目并将其用作标题,可以将水平和垂直标题添加到表中:

    QTableWidgetItem *valuesHeaderItem = new QTableWidgetItem(tr("Values"));
    tableWidget->setHorizontalHeaderItem(0, valuesHeaderItem);

注意,表中的行和列从零开始。

共同特征

这些便捷类都使用了相同的接口提供了一些基于项的特色功能。在以下各节中,我们将针对不同的部件提供一些示例。查看 模型/视图类 列表,可以获取有关所使用的每个函数的用法的更多详细信息。

隐藏项目

有时需要在项目视图部件中隐藏项目,而不是删除它们。上面所有的部件的项目都可以隐藏,以后再显示。可以通过调用 isItemHidden() 函数确定某个项目是否隐藏,并且可以使用 setItemHidden() 隐藏该项目。

由于此操作是基于项目的,因此对于所有三个便捷类都可以使用相同的功能。

选择项

选择项目的方式由部件的选择模式( QAbstractItemView::SelectionMode )控制。此属性控制用户是否可以选择一个或多个项目,并且在多个项目选择中控制选择是否必须是连续范围的项目。对于所有上述部件,选择模式都以相同的方式工作。

单项选择: 当用户需要从部件中选择单个项目时,默认的 SingleSelection 模式最合适。在此模式下,当前项目和所选项目相同。
多项目选择: 在这种模式下,用户可以在不更改现有选择的情况下切换部件中任何项目的选择状态,就像非独占复选框可以独立切换的方式一样。
扩展选择: 通常部件需要许多相邻的项目被选择,例如在电子表格中的部件,需要 ExtendedSelection 模式。在这种模式下,可以用鼠标和键盘选择窗口部件中连续范围内的项目。如果使用修饰键,则还可以对控件中与其他被选择的项不相邻的项进行选择。 如果用户在不使用修饰键的情况下选择了项目,则会清除现有选择。

使用 selectedItems() 函数读取窗口部件中的所选项目,从而提供可以迭代的相关项目的列表。例如,我们可以使用以下代码找到所选项目列表中所有数值的总和:

    const QList<QTableWidgetItem *> selected = tableWidget->selectedItems();
    int number = 0;
    double total = 0;

    for (QTableWidgetItem *item : selected) {
        bool ok;
        double value = item->text().toDouble(&ok);

        if (ok && !item->text().isEmpty()) {
            total += value;
            number++;
        }
    }

请注意,对于单选模式,当前项目就是被选择的项目。在多选和扩展选择模式下,取决于用户形成选择的方式,当前项目可能不在选择之内。

搜索

在项目视图部件中查找项目很实用。这三个项目视图便捷类都提供了一个通用的 findItems() 函数,以使其尽可能一致和简单。

根据从 Qt::MatchFlags 中选择的值指定的标准使用它们所包含的文本来搜索项。我们可以使用 findItems() 函数获得匹配项的列表:

    const QList<QTreeWidgetItem *> found = treeWidget->findItems(
        itemText, Qt::MatchWildcard);

    for (QTreeWidgetItem *item : found) {
        item->setSelected(true);
        // Show the item->text(0) for each item.
    }

如果上面的代码搜索包含指定文本的项目,列表和表部件同样适用。

在项目视图中使用拖放

模型/视图框架完全支持 Qt 的拖放功能。列表,表和树中的项目可以在视图中拖动,并且数据可以作为 MIME 编码的数据导入和导出。

标准视图自动支持内部拖放,可以移动项目来更改显示顺序。默认情况下,这些视图没有配置拖放功能,因为它们被配置为最简单,最常见的用途。要允许拖动项目,需要启用视图的某些属性,并且项目本身还必须允许进行拖动。

仅允许从视图中导出项目且不允许将数据放入其中的模型的要求比完全启用的拖放模型的要求少。

另请参阅 模型子类参考,以获取有关在新模型中启用拖放支持的更多信息。

使用便捷视图类

默认情况下,与 QListWidgetQTableWidgetQTreeWidget 一起使用的每种项目类型都配置为使用不同的标志集。 例如,每个 QListWidgetItemQTreeWidgetItem 最初都是启用的,可检查的,可选的,并且可用作拖放操作的源。每个 QTableWidgetItem 也可以进行编辑,并用作拖放操作的目标。

尽管所有标准项都为拖放设置了一个或两个标志,但是通常需要在视图本身中设置各种属性来使它启用对拖放操作的内建支持:

  • 启用项目拖拽,要将视图的 dragEnabled 属性设置为 true
  • 要允许用户将内部或者外部的项目放入视图中,需要设置视图的 viewport() acceptDrops 属性为 true
  • 要显示现在用户拖拽的项目将要放置的位置,需要设置 showDropIndicator 属性。这为用户提供了有关视图内项目放置的连续更新信息。

例如,我们可以使用以下代码在列表部件中拖放:

QListWidget *listWidget = new QListWidget(this);
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
listWidget->setDragEnabled(true);
listWidget->viewport()->setAcceptDrops(true);
listWidget->setDropIndicatorShown(true);

该列表部件允许在视图内到处复制项目,甚至允许用户在包含相同数据类型的视图之间拖动项目。在两种情况下,都是复制而不是移动项目。

为了使用户能够在视图内移动项目,我们必须设置列表部件的 dragDropMode

listWidget->setDragDropMode(QAbstractItemView::InternalMove);

在模型/视图类中使用拖放

设置拖放视图的方式与便捷视图类相同。例如,可以使用与 QListWidget 相同的方式来设置 QListView

QListView *listView = new QListView(this);
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
listView->setDragEnabled(true);
listView->setAcceptDrops(true);
listView->setDropIndicatorShown(true);

由于对视图显示的数据的访问由模型控制,因此所使用的模型还必须提供对拖放操作的支持。可以通过重新实现 QAbstractItemModel::supportedDropActions() 函数来指定模型支持的动作。例如,使用以下代码启用复制和移动操作:

Qt::DropActions DragDropListModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

尽管可以给出 Qt::DropActions 中值的任意组合,但是需要编写模型来支持它们 例如,要允许 Qt::MoveAction 与列表模型一起正确使用,该模型必须直接或通过从其基类继承实现来提供 QAbstractItemModel::removeRows() 的实现。

启用项目拖放

通过重新实现 QAbstractItemModel::flags() 函数以提供适当的标志,模型向视图指示可以拖动哪些项目,哪些将接受放置。

例如,一个提供基于 QAbstractListModel 的简单列表的模型可以通过确保返回的标志包含 Qt::ItemIsDragEnabledQt::ItemIsDropEnabled 值来启用每个项目的拖放操作:

Qt::ItemFlags DragDropListModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QStringListModel::flags(index);

    if (index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
    else
        return Qt::ItemIsDropEnabled | defaultFlags;
}

注意,可以将项目拖放到模型的顶层,但是仅对有效项目有效。

在上面的代码中,由于模型是从 QStringListModel 派生的,我们通过调用重新实现的 flags() 函数来获取默认的标志集。

编码导出的数据

当通过拖放操作从模型中导出数据项时,会将它们编码为与一种或多种 MIME 类型相对应的格式。通过重新实现 QAbstractItemModel::mimeTypes() 函数并返回标准 MIME类型的列表,声明了可用于项目的MIME类型。

例如,仅提供纯文本的模型将提供以下实现:

QStringList DragDropListModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list";
    return types;
}

该模型还必须提供代码以被告知的格式编码数据。可以通过重新实现 QAbstractItemModel::mimeData() 函数来提供 QMimeData 对象来实现该功能,就像其他任何拖放操作一样。

以下代码显示了与给定索引列表相对应的每一项数据如何被编码为纯文本并存储在 QMimeData 对象中。

QMimeData *DragDropListModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *mimeData = new QMimeData;
    QByteArray encodedData;

    QDataStream stream(&encodedData, QIODevice::WriteOnly);

    for (const QModelIndex &index : indexes) {
        if (index.isValid()) {
            QString text = data(index, Qt::DisplayRole).toString();
            stream << text;
        }
    }

    mimeData->setData("application/vnd.text.list", encodedData);
    return mimeData;
}

由于向函数提供了模型索引列表,该方法很通用,可以在分层模型和非分层模型中使用。

注意,必须将自定义数据类型声明为 元对象,并且必须为其实现流运算符。有关详细信息,请参见 QMetaObject 类描述。

将放置的数据插入到模型中

任何给定模型处理放置数据的方式取决于其类型(列表,表或树)以及其内容可能呈现给用户的方式。通常,保存放置数据的方法就是最适合模型底层数据存储的方法。

不同类型的模型倾向于以不同方式处理放置的数据。列表和表模型仅提供了用于存储数据项的平面结构。因此,当将数据放置到视图中的现有项目上时,他们可能会插入新的行(和列),或者可能会使用提供的某些数据覆盖模型中项目的内容。树模型通常能够将包含新数据的子项添加到其底层数据存储中,因此就用户而言,其行为更具可预测性。

底层的数据由模型的 QAbstractItemModel::dropMimeData() 重新实现来处理。例如,处理字符串的简单列表的模型可以提供一种实现,该实现将放置到现有项目上的数据与放置到模型顶层(即到无效项目)的数据分开处理。

通过重新实现 QAbstractItemModel::canDropMimeData() ,模型可以禁止放置到某些项目,或者取决于放置的数据。

该模型首先必须确保执行操作,所提供的数据采用可以使用的格式,并且其在模型中的目的地是有效的:

bool DragDropListModel::canDropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    Q_UNUSED(action);
    Q_UNUSED(row);
    Q_UNUSED(parent);

    if (!data->hasFormat("application/vnd.text.list"))
        return false;

    if (column > 0)
        return false;

    return true;
}
bool DragDropListModel::dropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    if (!canDropMimeData(data, action, row, column, parent))
        return false;

    if (action == Qt::IgnoreAction)
        return true;

如果提供的数据不是纯文本,或者为放置指定的列号无效,则简单的一列字符串列表模型可以指示失败。

根据要插入模型的数据是否被放到现有项目上,其处理方式有所不同。在这个简单的示例中,我们希望允许在现有项目之间,列表中的第一个项目之前以及最后一个项目之后进行放置。

发生放置时,对应于父项的模型索引将是有效的(指示该放置发生在某个项目上),或者将是无效的(指示该放置发生在视图中与模型顶层相对应的某处)。

    int beginRow;

    if (row != -1)
        beginRow = row;

最初,我们检查提供的行号,以查看是否可以使用它向模型中插入项目,而不管父索引是否有效。

    else if (parent.isValid())
        beginRow = parent.row();

如果父模型索引有效,则该放置到项目上。在这个简单的列表模型中,我们找出项目的行号,并使用该值将放置的项目插入模型的顶层。

    else
        beginRow = rowCount(QModelIndex());

当视图中的其他位置发生拖放并且行号不可用时,我们会将项目追加到模型的顶层。

在分层模型中,当某项发生放置时,最好将新项作为该项的子项插入模型中。在此处显示的简单示例中,模型只有一个级别,因此此方法不合适。

解码导入的数据

dropMimeData() 的每个实现还必须解码数据并将其插入到模型的底层数据结构中。

对于简单的字符串列表模型,可以对编码的项目进行解码并将其流式传输到 QStringList 中:

    QByteArray encodedData = data->data("application/vnd.text.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;

    while (!stream.atEnd()) {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }

然后可以将字符串插入底层数据存储中。为了保持一致,可以通过模型自己的接口来完成此操作:

    insertRows(beginRow, rows, QModelIndex());
    for (const QString &text : qAsConst(newItems)) {
        QModelIndex idx = index(beginRow, 0, QModelIndex());
        setData(idx, text);
        beginRow++;
    }

    return true;
}

注意,该模型通常需要重新实现 QAbstractItemModel::insertRows()QAbstractItemModel::setData() 函数。

代理模型

在模型/视图框架中,单个模型提供的数据项可以被任意数量的视图共享,并且每个视图可能以完全不同的方式表示相同的信息。自定义视图和委托对于完全相同的数据进行不同的显示提供了有效方法。但是,应用程序通常需要提供对相同数据的不同的处理版本的常规视图,例如对项列表的不同排序视图。

尽管将排序和筛选操作作为视图的内部功能执行似乎是适当的,但是这种方法不允许多个视图共享这种可能代价高昂的操作的结果。另一种方法,涉及到模型本身的排序,会导致类似的问题,即每个视图都必须显示根据最近的处理操作组织的数据项。

为了解决此问题,模型/视图框架使用代理模型来管理各个模型和视图之间提供的信息。从视图的角度来看,代理模型与普通的模型类似,视图从源模型访问数据。模型/视图框架使用的信号槽机制确保无论在其自身与源模型之间放置多少代理模型,每个视图都将在合适的时机进行更新。

使用代理模型

可以在现有模型和任意数量的视图之间插入代理模型。Qt 提供了一个标准的代理模型 QSortFilterProxyModel,该模型通常被实例化并直接使用,但是也可以被子类化以提供自定义的过滤和排序功能。 QSortFilterProxyModel 类可以按以下方式使用:

    QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(parent);
    filterModel->setSourceModel(stringListModel);

    QListView *filteredView = new QListView;
    filteredView->setModel(filterModel);

由于代理模型是从 QAbstractItemModel 继承的,因此它们可以连接到任何类型的视图,并且可以在视图之间共享。它们还可以用于处理从其他代理模型获得的信息。

QSortFilterProxyModel 在应用程序中可被实例化后直接使用。通过子类化此类并实现所需的比较操作,可以创建更多专业的代理模型。

自定义代理模型

通常,代理模型中使用的处理类型涉及到将每个数据项从源模型中的原始位置映射到代理模型中的不同位置。在某些模型中,某些项在代理模型中可能没有相应的位置;这些模型正在过滤代理模型。视图使用代理模型提供的模型索引访问数据项,这些索引不包含有关源模型或原始项在该模型中的位置的信息。

QSortFilterProxyModel 允许在将源模型中的数据提供给视图之前对其进行筛选,还允许将源模型的内容作为预先排序的数据提供给视图。

自定义过滤模型

QSortFilterProxyModel 类提供了一个相当通用的过滤模型,并且可以在多种常见情况下使用。对于高级用户,可以将 QSortFilterProxyModel 子类化,从而提供一种使自定义过滤器得以实现的机制。

QSortFilterProxyModel 的子类可以重新实现两个虚函数,只要请求或使用来自代理模型的模型索引,就会调用这两个虚函数:

QSortFilterProxyModel 中上述函数的默认实现返回 true,以确保将所有项目都传递给视图。重新实现这些函数应返回 false,以过滤出单独的行和列。

自定义排序模型

QSortFilterProxyModel 实例使用 std::stable_sort() 函数在源模型中的项目和代理模型中的项目之间设置映射,从而将已排序的分层次的项目公开给视图,而无需修改源模型的结构。要提供这种自定义排序的功能,需要重新实现 lessThan() 函数来执行自定义比较。

模型子类参考

模型子类需要实现 QAbstractItemModel 基类中定义的许多虚函数。需要实现的这些函数的数量取决于模型的类型-它是否为视图提供简单的列表,表还是复杂的项目层次结构。从 QAbstractListModelQAbstractTableModel 继承的模型可以利用这些类提供的函数的默认实现。以树状结构显示数据项的模型实现 QAbstractItemModel 中的许多虚函数提。

在模型子类中需要实现的函数可以分为三类:

  • 项目数据处理: 所有模型都需要实现一些函数,以使视图和委托能够查询模型的尺寸,检查项目并检索数据。
  • 导航和索引创建: 层次模型需要实现视图可以调用的函数,以导航它们公开的树状结构,并获取项目的模型索引。
  • 拖放支持和 MIME 类型处理: 模型继承了控制内部和外部拖放操作执行方式的函数。这些函数允许使用其他组件和应用程序可以理解的 MIME 类型来描述数据项。

项目数据处理

模型可以提供对数据的不同级别的访问:它们可以是简单的只读组件,某些模型可以支持调整大小的操作,而其他模型则可以编辑项目。

只读访问

要提供对模型数据的只读访问,必须在模型的子类中实现以下功能:

flags()用于其他组件来获取有关模型提供的每个项目的信息。在许多模型中,标志的组合应包括 Qt::ItemIsEnabledQt::ItemIsSelectable
data()用于向视图和委托提供项目数据。通常,模型只需要为 Qt::DisplayRole 和任何特定应用程序的用户角色提供数据,但是为 Qt::DisplayRoleQt::ToolTipRoleQt::AccessibleTextRoleQt::AccessibleDescriptionRole 提供数据也是一种好习惯。 有关与每个角色关联的类型的信息,请参见 Qt::ItemDataRole 枚举文档。
headerData()提供有关标题的数据信息。该信息仅由可显示标题信息的视图检索。
rowCount()提供模型公开的数据行数。

这四个函数必须在所有类型的模型中实现,包括列表模型( QAbstractListModel 子类)和表模型( QAbstractTableModel 子类)。

此外,必须在 QAbstractTableModelQAbstractItemModel 的直接子类中实现以下功能:

columnCount() 提供模型公开的数据列数。列表模型不提供此功能,因为它已在QAbstractListModel中实现。

可编辑的项目

可编辑模型允许修改数据项,还可以提供允许插入和删除行和列的函数。要启用编辑,必须正确实现以下功能:

flags()必须为每个项目返回适当的标志组合。特别是,此函数返回的值除了应用于只读模型中的项的值外,还必须包括 Qt::ItemIsEditable
setData()用于修改与指定模型索引关联的数据项。 为了能够接受用户界面元素提供的用户输入,此功能必须处理与 Qt::EditRole 相关的数据。 该实现还可以接受与 Qt::ItemDataRole 指定的许多不同种类的角色相关联的数据。更改数据项后,模型必须发出 dataChanged() 信号以将更改通知其他组件。
setHeaderData()用于修改水平和垂直标题信息。更改数据项后,模型必须发出 headerDataChanged() 信号以将更改通知其他组件。

可调整大小的模型

所有类型的模型都可以支持行的插入和删除。表模型和层次结构模型也可以支持列的插入和删除。在模型尺寸发生变化 之前之后 ,都必须通知其他组件有关模型尺寸的变化。可以实现以下函数以允许调整模型的大小,但是实现必须确保调用合适的函数以通知附加的视图和委托:

insertRows() 用于向所有类型的模型添加新行和数据项。函数的实现必须在将新行插入任何底层数据结构 之前 调用 beginInsertRows()然后立即 调用 endInsertRows()
removeRows()用于从所有类型的模型中删除行及其包含的数据项。在从任何底层数据结构中删除行 之前,必须调用 beginRemoveRows()然后立即 调用 beginRemoveRows()
insertColumns()用于向表模型和层次结构模型添加新的列和数据项。函数的实现必须在将新列插入任何底层数据结构 之前 调用 beginInsertColumns()然后立即 调用 endInsertColumns()
removeColumns()用于从表模型和层次模型中删除列及其包含的数据项。函数的实现必须在从任何基础数据结构中删除列 之前 调用 beginRemoveColumns()然后立即 调用 endRemoveColumns()

通常,如果操作成功,这些函数应返回true。但是,在某些情况下,操作可能仅部分成功;例如,如果可以插入少于指定数量的行。在这种情况下,模型应返回 false 来提示失败,让连接到该模型的组件处理这种情况。

在调整大小的 API 函数中发出信号使附加的组件有机会在任何数据变得不可用之前采取措施。使用 beginend 函数对插入和删除操作进行的封装也使模型能够正确管理持久模型索引。

通常,beginend 函数能够通知其他组件有关模型底层结构的更改。对于模型结构的更复杂的更改,可能涉及内部重组,数据排序或任何其他结构更改,有必要按照以下顺序:

该顺序可用于任何结构更新,以代替更高级,更方便的受保护方法。例如,如果一个200万行的模型需要删除所有奇数行,那就是100万个不连续的范围,每行1个元素。可以使用 beginRemoveRows 和 `endRemoveRows 一百万次,但这显然效率不高。相反,这可以作为一个单独的布局更改来表示,它一次更新所有必需的持久性索引。

懒惰的模型数据

懒散填充模型数据可以有效地延迟对模型信息的请求,直到视图实际需要它为止。

一些模型需要从远程源获取数据,或者必须执行耗时的操作才能获取有关数据组织方式的信息。由于视图通常要求尽可能多的信息以准确显示模型数据,因此限制返回给它们的信息量以减少不必要的后续数据请求可能很有用。

在分层模型中查找给定项目的子项数是一项昂贵的操作,确保仅在必要时才调用模型的 rowCount() 实现是有用的。在这种情况下,可以重新实现 hasChildren() 函数,以提供一种廉价的方法来查看视图是否存在子项,对于 QTreeView,则为其父项绘制适当的装饰。

无论 hasChildren() 的重新实现返回 true 还是 false,该视图都不必调用 rowCount() 来找出存在多少个子项。例如,如果 QTreeView 未扩展父项则就不需要知道有多少个子级。

如果知道许多项目将有子项,那么重新实现 hasChildren() 以无条件返回 true 有时是一种有用的方法。这样可以确保以后可以检查每个项目的子项,同时尽可能快地对模型数据进行初始填充。唯一的缺点是,在用户试图查看不存在的子项之前,没有子项的项目可能会在某些视图中显示不正确。

创建导航和模型索引

分层结构的模型需要提供一些函数,视图可以调用这些函数来导航它们公开的树状结构,并获取项目的模型索引。

父项和子项

由于公开给视图的结构是由底层数据结构决定的,因此由每个模型子类通过提供以下函数的实现来创建自己的模型索引:

index()给定父项的模型索引,此函数允许视图和委托访问该项的子项。如果找不到有效的子项-对应于指定的行,列和父模型索引,则该函数必须返回 QModelIndex() ,这是无效的模型索引。
parent()提供与任何给定子项的父项相对应的模型索引。如果指定的模型索引对应于模型中的顶级项,或者模型中没有有效的父项,则该函数必须返回使用空 QModelIndex() 构造函数创建的无效模型索引。

以上两个函数都使用 createIndex() 工厂函数来生成索引以供其他组件使用。通常,模型会为此函数提供一些唯一的标识符,以确保以后可以将模型索引与其对应的项目重新关联。

拖放支持和 MIME 类型处理

模型/视图类支持拖放操作,提供足以用于许多应用程序的默认行为。但是,也可以自定义拖放操作期间项目的编码方式,无论是复制项目还是移动项目以及如何将其插入现有模型。

另外,便捷视图类实现了专门的行为,该行为应与现有开发人员所期望的行为紧密相随。便捷视图 部分提供了此行为的概述。

MIME 数据

默认情况下,内置模型和视图使用内部 MIME 类型( application / x-qabstractitemmodeldatalist )来传递有关模型索引的信息。这将指定项目列表的数据,其中包含每个项目的行号和列号,以及有关每个项目支持的角色的信息。

MIME 类型编码的数据可以通过调用带有 QModelIndexList 参数的 QAbstractItemModel::mimeData() 函数获取。

在自定义模型中实现拖放支持时,可以通过重新实现以下函数以专用格式导出数据项:

mimeData()可以重新实现此函数,以返回默认 `application / x-qabstractitemmodeldatalist` 内部 `MIME` 类型以外的格式的数据。子类可以从基类获取默认的 QMimeData 对象,并以其他格式向其添加数据。

对于许多模型,以 MIME 类型表示的通用格式(例如 text / plain和image / png )提供项目的内容很有用。请注意,可以使用 QMimeData::setImageData()QMimeData::setColorDataQMimeData::setHtml() 函数轻松地将图像,颜色和 HTML 文档添加到 QMimeData 对象。

接受放置的数据

在视图上执行拖放操作时,将查询底层模型,以确定其支持的操作类型以及可以接受的 MIME 类型。此信息由 QAbstractItemModel::supportedDropActionsQAbstractItemModel::mimeTypes() 函数提供。不覆盖 QAbstractItemModel 提供的实现的模型支持复制操作和项的默认内部 MIME 类型。

当序列化的项目数据放到视图上时,使用其 QAbstractItemModel::dropMimeData() 实现将数据插入当前模型。该函数的默认实现将永远不会覆盖模型中的任何数据。而是尝试将数据项作为项的兄弟或项的子项插入。

要利用 QAbstractItemModel 的默认实现来实现内置的 MIME 类型,新模型必须提供以下函数的重新实现:

insertRows()这些函数使模型可以使用 QAbstractItemModel::dropMimeData() 提供的现有实现自动插入新数据。
insertColumns()
setData()允许用项目填充新的行和列。
setItemData()此函数为填充新项目提供了更有效的支持。

要接受其他形式的数据,必须重新实现以下函数:

supportedDropActions()用于返回 放置动作 的组合,指示模型接受的拖放操作的类型。
mimeTypes()用于返回可由模型解码和处理的 MIME 类型的列表。通常,支持输入模型的 MIME 类型与对数据进行编码以供外部组件使用时可以使用的 MIME 类型相同。
dropMimeData()对通过拖放操作传输的数据执行实际的解码,确定将在模型中设置的位置,并在必要时插入新的行和列。在子类中如何实现此函数取决于每个模型公开的数据的要求。

如果 dropMimeData() 函数的实现通过插入或删除行或列来更改模型的尺寸,或者如果修改了数据项,则必须注意确保发出所有相关信号。简单地调用子类中其他函数的重新实现(例如 setData()insertRows()insertColumns() )可能很有用,以确保模型表现一致。

为了确保拖动操作正常工作,重要的是重新实现以下从模型中删除数据的函数:

有关在项目视图中进行拖放的更多信息,请参阅 在项目视图中使用拖放

便捷视图

便捷视图(QListWidgetQTableWidgetQTreeWidget)将覆盖默认的拖放功能,以提供较不灵活但更自然的行为,适用于许多应用程序。例如,由于更常见的是将数据放入 QTableWidget 中的单元格中,用传输的数据替换现有内容,因此底层模型将设置目标项目的数据,而不是在模型中插入新的行和列。有关在方便视图中拖放的更多信息,请参阅 在项目视图中使用拖放

针对大量数据的性能优化

canFetchMore() 函数检查父级是否有更多可用数据,并相应地返回 truefalsefetchMore() 函数根据指定的父级获取数据。这两个函数可以组合在一起,例如,在涉及增量数据的数据库查询中组合以填充 QAbstractItemModel。我们重新实现 canFetchMore() 来指示是否有更多数据要提取,并根据需要使用 fetchMore() 来填充模型。

另一个示例是动态填充的树模型,当树模型中的分支扩展时,我们重新实现 fetchMore()

如果重新实现 fetchMore() 将行添加到模型中,则需要调用 beginInsertRows()endInsertRows()。另外,必须重新实现 canFetchMore()fetchMore(),因为它们的默认实现返回 false 并且不执行任何操作。

模型/视图类

这些类使用模型/视图设计模式,其中(模型中的)底层数据与用户(视图中)呈现和操作数据的方式保持分离。

说明
QAbstractItemDelegate用于显示和编辑模型中的数据项
QAbstractItemModel项目模型类的抽象接口
QAbstractItemView项目视图类的基本功能
QAbstractListModel可以被子类化创建一维列表模型的抽象模型
QAbstractProxyModel代理项目模型的基类,可以执行排序,过滤或其他数据处理任务
QAbstractTableModel可以被子类化创建表模型的抽象模型
QColumnView列视图的模型/视图实现
QConcatenateTablesProxyModel代理多个源模型,并连接它们的行
QDataWidgetMapper数据模型的一部分到部件之间的映射
QFileSystemModel本地文件系统的数据模型
QHeaderView项目视图的标题行或标题列
QIdentityProxyModel代理未经修改的源模型
QItemDelegate显示和编辑来自模型的数据项的工具
QItemEditorCreator无需子类 QItemEditorCreatorBase 即可创建项目编辑器创建者库
QItemEditorCreatorBase实现新项目编辑器创建者时必须子类化的抽象基类
QItemEditorFactory用于在视图和委托中编辑项目数据的部件
QItemSelection管理有关模型中选定项目的信息
QItemSelectionModel跟踪视图的选定项目
QItemSelectionRange管理有关模型中选定项目范围的信息
QListView模型上的列表或图标视图
QListWidget基于项目的列表部件
QListWidgetItemQListWidget 项目视图类一起使用的项目
QModelIndex用于在数据模型中定位数据
QPersistentModelIndex用于在数据模型中定位数据
QSortFilterProxyModel支持对在另一个模型和视图之间传递的数据进行排序和过滤
QStandardItemQStandardItemModel 类一起使用的项目
QStandardItemEditorCreator无需子类化 QItemEditorCreatorBase 即可注册部件的可能新
QStandardItemModel用于存储自定义数据的通用模型
QStringListModel向视图提供字符串的模型
QStyledItemDelegate显示和编辑来自模型的数据项的工具
QTableView表格视图的默认模型/视图实现
QTableWidget具有默认模型的基于项目的表视图
QTableWidgetItemQTableWidget 类一起使用的项目
QTableWidgetSelectionRange在不使用模型索引和选择模型的情况下与模型中的选择进行交互的方法
QTreeView树视图的默认模型/视图实现
QTreeWidget使用预定义树模型的树视图
QTreeWidgetItemQTreeWidget 便捷类一起使用的项目
QTreeWidgetItemIterator遍历 QTreeWidget 实例中的项目的方法

相关示例

另请参阅 项目视图拼图示例

模型视图教程

每个 UI 开发人员都应该了解模型视图编程,本教程的目的是让您轻松理解有关模型视图的相关知识。

表格,列表和树部件是 GUI 中经常使用的组件。这些部件可以通过两种不同的方式访问其数据。传统方式是,这些部件包含用于存储数据的内部容器。这种方法非常直观,但是,在许多应用程序中,它会导致数据同步问题。第二种方法是模型/视图编程,其中部件不维护内部数据容器。他们通过标准化接口访问外部数据,因此避免了数据重复。乍一看,这似乎很复杂,但是如果您仔细看一看,不仅容易掌握,而且模型/视图编程的许多好处也变得更加明显。

treeview

在此过程中,我们将了解 Qt 提供的一些基本技术,例如:

  • 标准部件和模型视图部件的区别
  • 窗体和模型之间的适配器
  • 开发一个简单的模型视图的应用程序
  • 预定义模型
  • 中间主题,比如:
    • 树形视图
    • 选项
    • 委托
    • 模型调试测试

您还将了解到新的应用程序是否可以通过模型/视图编程更容易地编写,或者经典的标准部件是否也可以工作。

本教程中的代码您可以编辑修改或者集成到您的项目中去。 源码在 Qtexamples/widgets/tutorials/modelview 目录。

详见 参考文档

1. 介绍

模型/视图是一种将数据从视图中分离出来,来处理数据集的一种技术。标准部件并不是为将数据从视图中分离出来而设计的,这就是为什么 Qt 会有两种不同类型的部件。这两种部件看起来都一样,但是它们与数据之间的交互方式是不同的。

标准部件使用的数据最为部件的一部分。

视图类操作的是外部的数据(模型)。

1.1 标准部件

让我们仔细看一下标准表部件。表格部件是用户可以更改的数据元素的 2D 数组。通过读取和写入表部件提供的数据元素,可以将表部件集成到程序流中。该方法非常直观,在许多应用程序中很有用,但是使用标准表窗口部件显示和编辑数据库表可能会出现问题。数据的两个副本必须协调一致:一个在部件外部;另一个在部件外部。开发人员负责同步两个版本。除此之外,表示和数据的紧密耦合使编写单元测试更加困难。

1.2 使用模型/视图解决

模型/视图提供了一个使用更通用体系结构的解决方案。模型/视图消除了标准控件可能出现的数据一致性问题。模型/视图还可以更容易地使用同一数据的多个视图,因为一个模型可以传递给多个视图。最重要的区别是模型/视图部件不在表单元格后面存储数据。实际上,它们直接根据您的数据进行操作。因为视图类不知道数据的结构,所以需要提供一个包装器,使数据符合 QAbstractItemModel 接口。视图使用此接口读取和写入数据。实现 QAbstractItemModel 类的任何实例都称为模型。一旦视图接收到指向模型的指针,它将读取和显示其内容,并成为其编辑器。

1.3 模型/视图部件概览

下面是模型/视图部件及其对应的标准部件。

部件标准部件
(基于项的便捷类)
模型/视图 视图类
(使用外部数据)
QListWidgetQListView
QTableWidgetQTableView
QTreeWidgetQTreeView
QColumnView s显示列表层次结构的树视图
QComboBox 既可以用作视图类,也可以用作传统部件

1.4 在表单和模型之间使用适配器

在表单和模型之间使用适配器非常方便。我们可以直接从表内部编辑存储在表中的数据,但是在文本字段中编辑数据更为方便。在对部件的一个数据而不是数据集操作时,模型/视图并没有提供对应的方法将数据和视图分离开。比如 QLineEditQCheckBox...因此我们需要一个适配器来将表单连接到数据源。

QDataWidgetMapper 是一个很好的解决方案,因为它可以将表单部件映射到表行,并且为数据库表构建表单非常容易。

widgetmapper

适配器的另一个例子是 QCompleterQt 使用 QCompleterQt 部件(如 QComboBox 和 如下图所示的 QLineEdit)中提供自动补全功能。QCompleter使用模型作为其数据源。

qcompleter

2. 一个简单的模型/视图应用程序

如果要开发模型/视图应用程序,应该从哪里开始?我们建议从一个简单的示例开始,并逐步扩展它。这样更容易理解模型/视图架构。事实证明,在调用 IDE 之前尝试详细了解模型/视图体系结构对于许多开发人员来说并不方便。从具有演示数据的简单模型/视图应用程序开始要容易得多。试试看!只需将以下示例中的数据替换为您自己的数据即可。

以下是7个非常简单和独立的应用程序,它们展示了模型/视图编程的不同方面。可以在 examples/widgets/tutorials/modelview 目录中找到源代码。

2.1 只读的表

我们从使用 QTableView 来显示数据的应用程序开始。稍后我们将添加编辑功能。

(文件: examples/widgets/tutorials/modelview/1_readonly/main.cpp)

// main.cpp
#include <QApplication>
#include <QTableView>
#include "mymodel.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTableView tableView;
    MyModel myModel;
    tableView.setModel(&myModel);
    tableView.show();
    return a.exec();
}

main() 函数:

这是有趣的部分:我们创建 MyModel 的实例并使用 tableView.setModel(&myModel);。 将其指针传递给 tableViewtableView 将调用它收到的指针的方法来找出两件事:

  • 需要显示多少行和列。
  • 每个单元格中应该显示什么内容。

模型需要一些代码来响应以上这些。

我们有一个表数据集,因此让我们从 QAbstractTableModel 开始,因为它比更通用的 QAbstractItemModel 更易于使用。

(文件:examples/widgets/tutorials/modelview/1_readonly/mymodel.h)

// mymodel.h
#include <QAbstractTableModel>

class MyModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MyModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};

QAbstractTableModel 需要实现三个抽象方法。

(文件:examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp)

// mymodel.cpp
#include "mymodel.h"

MyModel::MyModel(QObject *parent)
    : QAbstractTableModel(parent)
{
}

int MyModel::rowCount(const QModelIndex & /*parent*/) const
{
   return 2;
}

int MyModel::columnCount(const QModelIndex & /*parent*/) const
{
    return 3;
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
       return QString("Row%1, Column%2")
                   .arg(index.row() + 1)
                   .arg(index.column() +1);

    return QVariant();
}

行数和列数由 MyModel::rowCount()MyModel::columnCount() 提供。当视图必须知道单元格的文本是什么时,它将调用方法 MyModel::data()。行和列信息由参数 index 指定,并且角色设置为 Qt::DisplayRole。下一节将介绍其他角色。在我们的示例中,生成了应显示的数据。在实际的应用程序中,MyModel 会有一个名为 MyData 的成员,该成员充当所有读取和写入操作的目标。

这个小例子说明了模型的被动性质。该模型不知道何时使用它或需要哪些数据。每次视图请求时,它仅提供数据。

当需要更改模型数据时会发生什么?视图如何认识到数据已更改并且需要再次读取?该模型必须发射一个信号,该信号指示已更改了哪些单元格范围。这将在第2.3节中演示。

2.2 使用角色扩展只读表格示例

除了控制视图显示的文本之外,模型还控制文本的外观。当我们稍微改变模型时,我们得到以下结果:

readonlytable_role

实际上,除了 data() 方法外,无需更改其他任何内容即可设置字体,背景色,对齐方式和复选框。下面是产生上面所示结果的 data() 方法。不同之处在于,这次我们使用参数 int 角色根据其值返回不同的信息。

(文件: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp)

// mymodel.cpp
QVariant MyModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    int col = index.column();
    // generate a log message when this method gets called
    qDebug() << QString("row %1, col%2, role %3")
            .arg(row).arg(col).arg(role);

    switch (role) {
    case Qt::DisplayRole:
        if (row == 0 && col == 1) return QString("<--left");
        if (row == 1 && col == 1) return QString("right-->");

        return QString("Row%1, Column%2")
                .arg(row + 1)
                .arg(col +1);
    case Qt::FontRole:
        if (row == 0 && col == 0) { //change font only for cell(0,0)
            QFont boldFont;
            boldFont.setBold(true);
            return boldFont;
        }
        break;
    case Qt::BackgroundRole:
        if (row == 1 && col == 2)  //change background only for cell(1,2)
            return QBrush(Qt::red);
        break;
    case Qt::TextAlignmentRole:
        if (row == 1 && col == 1) //change text alignment only for cell(1,1)
            return Qt::AlignRight + Qt::AlignVCenter;
        break;
    case Qt::CheckStateRole:
        if (row == 1 && col == 0) //add a checkbox to cell(1,0)
            return Qt::Checked;
        break;
    }
    return QVariant();
}

每个格式化属性将通过对 data() 方法的单独调用从模型中请求。角色参数用于让模型知道请求哪个属性:

枚举 Qt::ItemDataRole意义类型
Qt::DisplayRole文本QString
Qt::FontRole字体 QFont
BackgroundRole单元格背景的画笔QBrush
Qt::TextAlignmentRole文本对齐方式enum Qt::AlignmentFlag
Qt::CheckStateRole使用 QVariant() 取消复选框,使用 Qt::CheckedQt::UnChecked 设置复选框enum Qt::ItemDataRole

请参阅 Qt 明明控件文档了解有关 Qt::ItemDataRole 枚举功能的更多信息。

现在我们需要确定使用分离的模型如何影响应用程序的性能,因此让我们跟踪视图调用 data() 方法的频率。为了跟踪视图调用模型的频率,我们在 data() 方法中放置了一条调试语句,该语句记录到错误输出流中。在我们的小示例中,data() 将被调用 42 次。每次将光标悬停在该字段上时,都会再次调用 data(),每个单元格7次。这就是为什么在调用 data() 和缓存昂贵的查找操作时确保数据可用的重要原因。

2.3 表内的时钟

clock

我们仍然使用一个只读表,但是这次内容每秒更改一次,因为我们正在显示当前时间。

(文件:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    int col = index.column();

    if (role == Qt::DisplayRole && row == 0 && col == 0)
        return QTime::currentTime().toString();

    return QVariant();
}

缺少一些东西来使时钟滴答作响。我们需要每秒告诉视图时间已更改,并且需要再次读取。我们用一个计时器来做到这一点。在构造函数中,我们将其间隔设置为1秒,然后连接其超时信号。

(文件:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)

MyModel::MyModel(QObject *parent)
    : QAbstractTableModel(parent)
    , timer(new QTimer(this))
{
    timer->setInterval(1000);
    connect(timer, &QTimer::timeout , this, &MyModel::timerHit);
    timer->start();
}

(文件:examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp

槽函数:

void MyModel::timerHit()
{
    //we identify the top left cell
    QModelIndex topLeft = createIndex(0,0);
    //emit a signal to make the view reread identified data
    emit dataChanged(topLeft, topLeft, {Qt::DisplayRole});
}

我们通过发射 dataChanged() 信号要求视图再次读取左上角单元格中的数据。请注意,我们没有将 dataChanged 信号显式连接到视图。这在我们调用 setModel 时自动发生。

2.4 设置行和列的标题

标题可以通过调用视图的一个方法被隐藏: tableView->verticalHeader()->hide();

modelview-header

但是,标题内容是通过模型设置的,因此我们重新实现 headerData() 方法:

(文件:examples/widgets/tutorials/modelview/4_headers/mymodel.cpp

QVariant MyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
        switch (section) {
        case 0:
            return QString("first");
        case 1:
            return QString("second");
        case 2:
            return QString("third");
        }
    }
    return QVariant();
}

请注意,方法 headerData() 也具有角色参数,该角色与 MyModel::data() 中的含义相同。

最小编辑示例

在此示例中,我们将构建一个应用程序,该应用程序通过重复输入表单元格中的值来自动用内容填充窗口标题。为了能够轻松访问窗口标题,我们将 QTableView 放在 QMainWindow 中。

该模型决定编辑功能是否可用。我们仅需修改模型即可启用可用的编辑功能。这可以通过重新实现以下虚函数来完成:setData()flags()

(文件:examples/widgets/tutorials/modelview/5_edit/mymodel.h

// mymodel.h
#include <QAbstractTableModel>
#include <QString>

const int COLS= 3;
const int ROWS= 2;

class MyModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MyModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
private:
    QString m_gridData[ROWS][COLS];  //holds text entered into QTableView
signals:
    void editCompleted(const QString &);
};

我们使用二维数组 QString m_gridData 来存储我们的数据。这使 m_gridData 成为 MyModel 的核心。MyModel 的其余部分就像包装器一样,将 m_gridData 调整为 QAbstractItemModel 接口。我们还引入了 editCompleted() 信号,这使得将修改后的文本传输到窗口标题成为可能。

(文件:examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)

bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role == Qt::EditRole) {
        if (!checkIndex(index))
            return false;
        //save value from editor to member m_gridData
        m_gridData[index.row()][index.column()] = value.toString();
        //for presentation purposes only: build and emit a joined string
        QString result;
        for (int row = 0; row < ROWS; row++) {
            for (int col= 0; col < COLS; col++)
                result += m_gridData[row][col] + ' ';
        }
        emit editCompleted(result);
        return true;
    }
    return false;
}

每次用户编辑单元格时都会调用 setData()index 参数告诉我们哪个字段已被编辑,value 提供了编辑过程的结果。该角色将始终设置为 Qt::EditRole,因为我们的单元格仅包含文本。如果存在一个复选框,并且将用户权限设置为允许选中该复选框,则还将以角色设置为 Qt::CheckStateRole 进行调用。

(文件:examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)

Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
    return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}

单元格的各种属性可以使用 flags() 进行调整。

返回 Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled 足以显示一个可被单元格选中的编辑器。

如果编辑一个单元格所修改的数据多于该特定单元格中的数据,则该模型必须发射 dataChanged() 信号,以便读取已更改的数据。

中间主题

3.1 树视图

您可以将上面的示例转换为具有树视图的应用程序。只需将 QTableView 替换为 QTreeView,这将生成一个读/写树。不必对模型进行任何更改。树不会有任何层次结构,因为模型本身没有任何层次结构。

dummy_tree

QListViewQTableViewQTreeView 均使用了合并了列表、表和树的模型抽象。这样就可以让不同类型的视图类使用同一模型。

list_table_tree

到目前为止,我们在示例中使用的模型都是这样子的:

example_model

我们想呈现一棵真正的树。在上面的示例中包装了数据,以建立模型。这次我们使用 QStandardItemModel ,这是用于具有层次结构的数据的容器,也实现了 QAbstractItemModel。要显示树,必须用 QStandardItem 填充 QStandardItemModelQStandardItem 可以保存项目的所有标准属性,例如文本,字体,复选框或笔刷。

tree_2_with_algorithm

(文件:examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp)

// modelview.cpp
#include "mainwindow.h"

#include <QTreeView>
#include <QStandardItemModel>
#include <QStandardItem>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , treeView(new QTreeView(this))
    , standardModel(new QStandardItemModel(this))
{
    setCentralWidget(treeView);

    QList<QStandardItem *> preparedRow = prepareRow("first", "second", "third");
    QStandardItem *item = standardModel->invisibleRootItem();
    // adding a row to the invisible root item produces a root element
    item->appendRow(preparedRow);

    QList<QStandardItem *> secondRow = prepareRow("111", "222", "333");
    // adding a row to an item starts a subtree
    preparedRow.first()->appendRow(secondRow);

    treeView->setModel(standardModel);
    treeView->expandAll();
}

QList<QStandardItem *> MainWindow::prepareRow(const QString &first,
                                              const QString &second,
                                              const QString &third) const
{
    return {new QStandardItem(first),
            new QStandardItem(second),
            new QStandardItem(third)};
}

我们只需实例化一个 QStandardItemModel 并向构造函数添加几个 QStandardItem。然后,我们可以建立分层数据结构,因为 QStandardItem 可以容纳其他 QStandardItem。节点在视图内折叠并展开。

3.2 处理选择

我们希望访问所选项目的内容,以便将其与层次结构级别一起输出到窗口标题中。

selection2

因此,让我们来创建几个项:

(文件: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp

#include "mainwindow.h"

#include <QTreeView>
#include <QStandardItemModel>
#include <QItemSelectionModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , treeView(new QTreeView(this))
    , standardModel(new QStandardItemModel(this))
{
    setCentralWidget(treeView);
    QStandardItem *rootNode = standardModel->invisibleRootItem();

    //defining a couple of items
    QStandardItem *americaItem = new QStandardItem("America");
    QStandardItem *mexicoItem =  new QStandardItem("Canada");
    QStandardItem *usaItem =     new QStandardItem("USA");
    QStandardItem *bostonItem =  new QStandardItem("Boston");
    QStandardItem *europeItem =  new QStandardItem("Europe");
    QStandardItem *italyItem =   new QStandardItem("Italy");
    QStandardItem *romeItem =    new QStandardItem("Rome");
    QStandardItem *veronaItem =  new QStandardItem("Verona");

    //building up the hierarchy
    rootNode->    appendRow(americaItem);
    rootNode->    appendRow(europeItem);
    americaItem-> appendRow(mexicoItem);
    americaItem-> appendRow(usaItem);
    usaItem->     appendRow(bostonItem);
    europeItem->  appendRow(italyItem);
    italyItem->   appendRow(romeItem);
    italyItem->   appendRow(veronaItem);

    //register the model
    treeView->setModel(standardModel);
    treeView->expandAll();

    //selection changes shall trigger a slot
    QItemSelectionModel *selectionModel = treeView->selectionModel();
    connect(selectionModel, &QItemSelectionModel::selectionChanged,
            this, &MainWindow::selectionChangedSlot);
}

视图在单独的选择模型中管理选择,可以使用 selectionModel() 方法进行检索。我们检索选择模型,以便将槽函数连接到其 selectionChanged() 信号。

(文件: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)

void MainWindow::selectionChangedSlot(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/)
{
    //get the text of the selected item
    const QModelIndex index = treeView->selectionModel()->currentIndex();
    QString selectedText = index.data(Qt::DisplayRole).toString();
    //find out the hierarchy level of the selected item
    int hierarchyLevel = 1;
    QModelIndex seekRoot = index;
    while (seekRoot.parent() != QModelIndex()) {
        seekRoot = seekRoot.parent();
        hierarchyLevel++;
    }
    QString showString = QString("%1, Level %2").arg(selectedText)
                         .arg(hierarchyLevel);
    setWindowTitle(showString);
}

我们通过调用 treeView->selectionModel()->currentIndex() 来获得与选择相对应的模型索引,并通过使用模型索引来获取字段的字符串。然后我们只计算项目的hierarchyLevel。顶级项没有父级,并且 parent() 方法将返回默认构造的 QModelIndex()。这就是为什么我们在迭代计算期间使用 parent() 方法迭代到最高级别的原因。

可以检索选择模型(如上所示),但也可以使用 QAbstractItemView::setSelectionModel 进行设置。这样就可以拥有3个具有同步选择的视图类,因为仅使用了一个选择模型实例。要在3个视图之间共享选择模型,请使用 selectionModel() 并通过 setSelectionModel 将结果分配给第二个和第三个视图类。

3.3 预定义模型

使用模型/视图的典型方法是包装特定数据以使其可用于视图类。但是,Qt 还为常见的底层数据结构提供了预定义的模型。如果可用的数据结构之一适合您的应用程序,那么预定义的模型可能是一个不错的选择。

QStringListModel存储字符串列表
QStandardItemModel存储任意分层结构的项目
QFileSystemModel
QDirModel
封装本地文件系统
QSqlQueryModel封装 SQL 结果集
QSqlTableModel封装 SQL 表
QSqlRelationalTableModel封装带外键的 SQL 表
QSortFilterProxyModel排序或者过滤其他模型

3.4 委托

到目前为止,在所有示例中,数据均以文本或复选框形式显示在单元格中,并以文本或复选框的形式进行编辑。提供这些表示和编辑服务的组件称为委托。我们只是刚刚开始使用委托,因为视图使用了默认委托。但是,假设我们想要一个不同的编辑器(例如,一个滑块或一个下拉列表),或者想象我们想要将数据显示为图形。让我们看一个名为 Star Delegate 的示例,其中的星星用于显示等级:

stardelegate

该视图具有 setItemDelegate() 方法,该方法将替换默认委托并安装自定义委托。可以通过创建从 QStyledItemDelegate 继承的类来编写新的委托。为了编写一个显示星星但没有输入功能的委托,我们只需要重写2个方法即可。

class StarDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    StarDelegate(QWidget *parent = 0);
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
    QSize sizeHint(const QStyleOptionViewItem &option,
                   const QModelIndex &index) const;
};

paint() 根据底层数据的内容绘制星形。可以通过调用 index.data() 查找数据。委托的 sizeHint() 方法用于获取每个星星的尺寸,因此该单元格将提供足够的高度和宽度来容纳星星。

如果要在视图类的网格内以自定义图形显示数据,则编写自定义委托是正确的选择。如果要离开网格,则可以不使用自定义委托,而使用自定义视图类。

Qt 文档中关于委托的其他参考:

3.5 使用 ModelTest 调试

模型的被动性质为程序员带来了新的挑战。模型中的不一致会导致应用程序崩溃。由于该模型会被视图中调用无数次,因此很难找出哪个调用使应用程序崩溃了,以及哪个操作导致了该问题。

Qt Labs 提供了一个名为 ModelTest 的软件,该软件可在您的程序运行时检查模型。每次更改模型时,ModelTest 都会扫描模型并使用断言报告错误。这对于树模型尤其重要,因为它们的层次结构性质即使是细微的不一致也会留下许多可能性。

与视图类不同,ModelTest 使用超出范围的索引来测试模型。这意味着您的应用程序可能会因 ModelTest 而崩溃,即使没有它也可以完美运行。因此,在使用 ModelTest 时,您还需要处理所有超出范围的索引。

4 附录

4.1 书籍

模型/视图编程在 Qt 文档中有相当广泛的介绍,但也有好几本好书。

  1. C++ GUI Programming with Qt 4 / Jasmin Blanchette, Mark Summerfield, Prentice Hall, 2nd edition, ISBN 0-13-235416-0. Also available in German: C++ GUI Programmierung mit Qt 4: Die offizielle Einführung, Addison-Wesley, ISBN 3-827327-29-6
  2. The Book of Qt4, The Art of Building Qt Applications / Daniel Molkentin, Open Source Press, ISBN 1-59327-147-6. Translated from Qt 4, Einführung in die Applikationsentwicklung, Open Source Press, ISBN 3-937514-12-0.
  3. Foundations of Qt Development / Johan Thelin, Apress, ISBN 1-59059-831-8.
  4. Advanced Qt Programming / Mark Summerfield, Prentice Hall, ISBN 0-321-63590-6. This book covers Model/View programming on more than 150 pages.

以下列表概述了上面列出的前三本书中包含的示例程序。其中一些为开发类似应用程序提供了非常好的模板。

示例名称使用的视图类使用的模型涵盖的方面 
Team LeadersQListviewQStringListModelBook 1, Chapter 10, Figure 10.6
Directory ViewerQTreeViewQDirModelBook 1, Chapter 10, Figure 10.7
Color NamesQListView应用于 QStringListModelQSortFilterProxyModelBook 1, Chapter 10, Figure 10.8
CurrenciesQTableView基于 QAbstractTableModel 的自定义模型 只读 Book 1, Chapter 10, Figure 10.10 
Cities QTableView基于 QAbstractTableModel 的自定义模型 读/写Book 1, Chapter 10, Figure 10.12
Boolean ParserQTreeView基于 QAbstractTableModel 的自定义模型只读 Book 1, Chapter 10, Figure 10.14
Track EditorQTableWidget自定义的委托并提供了自定义的编辑器 Book 1, Chapter 10, Figure 10.15
Four directory viewsQListView QTableView QTreeViewQDirModel演示使用多个视图Book2, Chapter 8.2
Address BookQListView QTableView QTreeView基于 QAbstractTableModel 的自定义模型读/写 Book2, Chapter 8.4
Address Book with sorting QSortfilterProxyModel引入排序和过滤功能Book2, Chapter 8.5
Address Book with checkboxes在模型/视图中引入复选框Book2, Chapter 8.6
Address Book with transposed grid基于 QAbstractProxyModel 的自定义代理模型引入自定义模型Book2, Chapter 8.7
Address Book with drag and drop引入托拖放支持Book2, Chapter 8.8
Address Book with custom editor引入自定义委托Book2, Chapter 8.9
ViewsQListView QTableView QTreeViewQStandardItemModel只读Book 3, Chapter 5, figure 5-3
BardelegateQTableView演示基于 QAbstractItemDelegate 的自定义委托Book 3, Chapter 5, figure 5-5
EditdelegateQTableView基于 QAbstractItemDelegate 的用于编辑的自定义委托Book 3, Chapter 5, figure 5-6
Singleitemview基于 QAbstractItemView 的自定义视图自定义视图Book 3, Chapter 5, figure 5-7
listmodelQTableView基于 QAbstractTableModel 的自定义模型只读Book 3, Chapter 5, Figure 5-8
treemodelQTreeView基于 QAbstractTableModel 的自定义模型只读Book 3, Chapter 5, Figure 5-10
edit integers[QListView]基于 QAbstractTableModel 的自定义模型读/写Book 3, Chapter 5, Listing 5-37, Figure 5-11
sortingQTableView应用于 QStringListModelQSortFilterProxyModel演示排序Book 3, Chapter 5, Figure 5-12

4.2 Qt 文档

Qt5.0提供了19个模型/视图示例。这些示例可以在 项目视图示例 页面上找到。

示例名称使用的视图类使用的模型涵盖的方面 
Address BookQTableViewQAbstractTableModel QSortFilterProxyModel使用QSortFilterProxyModel从一个数据池生成不同的子集
Basic Sort/Filter ModelQTreeViewQStandardItemModel QSortFilterProxyModel
Chart自定义视图QStandardItemModel设计与选择模型协作的自定义视图
Color Editor FactoryQTableWidget扩展一个带有新的自定义的编辑器的委托来选择颜色
Combo Widget Mapper使用 [QDataWidgetMapper] () 映射 QLineEditQTextEditQComboBoxQStandardItemModel演示了QComboBox如何作为视图类
Custom Sort/Filter ModelQTreeViewQStandardItemModel QSortFilterProxyModel子类化 QSortFilterProxyModel 用于高级排序和过滤
Dir ViewQTreeViewQFileSystemModel演示如何将模型指定给视图的非常小的示例
Editable Tree ModelQTreeView自定义树模型使用树的综合示例,演示了如何使用底层自定义模型编辑单元格和树结构
Fetch MoreQListView自定义列表模型动态变化的模型
Frozen ColumnQTableViewQStandardItemModel
InterviewMultiple 自定义项目模型多个视图
PixelatorQTableView自定义表模型实现一个自定义委托
PuzzleQListView自定义列表模型支持拖放的模型/视图
Simple DOM ModelQTreeView 自定义树模型自定义的只读的树模型的示例
Simple Tree ModelQTreeView自定义树模型自定义的只读的树模型的示例
Simple Widget Mapper使用 QDataWidgetMapper 映射 QLineEditQTextEditQSpinBoxQStandardItemModelQDataWidgetMapper 的基本用法
Spin Box DelegateQTableViewQStandardItemModel使用旋转框作为单元格编辑器的自定义委托
SpreadsheetQTableView自定义委托 
Star DelegateQTableWidget功能齐全的自定义委托示例

还提供了模型/视图技术的参考文档

Qt 中的多线程技术

Qt 提供一系列的类与函数来处理多线程。Qt 开发者们可以使用下面四种方法来实现多线程应用。

QThread: 低级 API 与可选的事件循环

作为 Qt 进行线程控制的基石,每一个 QThread 实例都代表并控制着一个线程。

您可以直接实例化 QThread,或建立子类。实例化一个 QThread 将附带一个并行事件循环,允许 QObject 槽函数在子线程执行。若子类化一个 QThread,程序可以在事件循环启动前初始化这个新线程;或者在无事件循环下运行并行代码。

另请参阅: QThread 类文档 以及示例代码 多线程范例 来了解如何使用 QThread。

QThreadPool 与 QRunnable: 线程重用

如果频繁地创建与销毁线程,资源开销将会非常大。为了减少这样额外的开销,可以重复使用一些现成的线程来执行新的任务。QThreadPool 就是这样一个保存着可重用的 QThead 的集合。

为了将代码放入 QThreadPool 的线程中运行,可以重写 QRunnable::run() 函数并实例化继承自 QRunnable 的子类。调用 QThreadPool::start() 函数可将 QRunnable 添加到 QThreadPool 的运行队列。一旦出现了一个可用的线程,它将会执行 QRunnable::run() 里的代码。

每一个 Qt 程序都会自带一个公共线程池,可以通过调用 QThreadPool::globalInstance() 来获取。公共线程池会自动维持着一定数量的线程,线程数为基于 CPU 核心数计算的最佳值。不过,您也可以显式创建并管理一个独立的 QThreadPool 。

Qt Concurrent: 使用高级 API

Qt Concurrent 模块提供了数个高级函数,用于处理一些常见的并行计算模式:map、filter 和 reduce。不同于使用 QThread 与 QRunnable,这些高级函数不需要使用底层线程原语,比如互斥锁与信号量。取而代之的是返回一个 QFuture 对象,它能够在传入的函数返回值就绪后检索该结果。QFuture 既可以用来查询计算进度,也可以暂停/恢复/取消计算。方便起见,QFutureWatcher 可以让您通过信号槽与 QFuture 进行交互。

Qt Concurrent 的 map、filter 和 reduce 算法会自动将计算过程分配到可用的处理器核心,由此,当下编写的程序在以后部署到更多核心的系统上时会被自动扩展。

此模块还提供了 QtConcurrent::run() 函数,可以将任何函数在另一个线程中运行。不过,QtConcurrent::run() 仅提供 map 、 filter 和 reduce 函数的一部分功能。QFuture 可以用于检索函数返回值,也可以用于查看线程是否处于运行中。然而,调用 QtConcurrent::run() 时只会使用一个线程,并且无法暂停/恢复/取消,也不能查询计算进度。

另请参阅: Qt Concurrent 模块文档以获取各个函数的详细信息。

WorkerScript: QML中的多线程

QML 类型 WorkerScript 可将 JavaScript 代码与 GUI 线程并行运行。

每个 WorkerScript 实例可附加一个 .js 脚本。当调用 WorkerScript.sendMessage() 时,脚本将会运行在一个独立的线程中(伴随一个独立的 QML 上下文)。在脚本运行结束后,WorkerScript 将会向 GUI 线程发送回复,后者会调用 WorkerScript.onMessage() 信号处理函数。

使用 WorkerScript,很像使用一个移入子线程工作的 QObject,数据通过信号槽在线程间进行传输。

另请参阅:WorkerScript 文档以获得实现脚本的详细信息,以及能够在线程间传输的数据类型列表。

选择合适的方法

如上文所述,Qt 提供了开发多线程应用的不同解决方案。对一个给定的程序,需要根据新线程的用途与线程的生命周期来决定正确的方案。下面是一组 Qt 多线程技术的功能对比表,以及对于一些范例较为推荐的解决方案。

解决方案对比

特性QThreadQRunnable 与 QThreadPoolQtConcurrent::run()Qt Concurrent(Map, Filter, Reduce)WorkerScript
语言C++C++C++C++QML
可以指定线程优先级
可以在线程中运行运行事件循环
可以通过信号获取数据更新是(通过 QObject 对象接收)是(通过 WorkerScript 接收)
可以使用信号控制线程是(通过 QThread 接收)是(通过 QFutureWatcher 接收)
可以通过QFuture 监视线程部分适用(译者注:仅可监视返回值,不可监视执行进度
内建的暂停/恢复/取消功能

示例用例

线程生命周期操作解决方案
单次调用在另一个线程中运行新的线性函数,可选地在运行期间进行更新进度。Qt 提供不同解决方案:
1. 重写 QThread::run() 并将函数放入其中,启动 QThread ,发射信号来更新进度。
2. 重写 QRunnable::run() ,将函数放入其中。将 QRunnable 添加到 QThreadPool 中。修改线程安全的变量以更新进度;
3. 使用 QtConcurrent::run() 运行函数。修改线程安全变量以更新进度。
单次调用在另一个线程中运行一个现成的函数,并取得它的返回值。使用 QtConcurrent::run() 运行函数。让 QFutureWatcher 在函数返回时发射 finish() 信号,并调用 QFutureWatcher::result() 来获取函数的返回值。
单次调用对一个容器的所有元素执行一个操作,使用所有可用的 CPU 核心。例如,从一组图片生成缩略图。使用 Qt Concurrent 的 QtConcurrent::filter() 函数选择容器元素,并用 QtConcurrent::map() 函数对每个元素执行操作。要将输出合并为单个结果,可以使用 QtConcurrent:: filteredReduced() 和 QtConcurrent::mappedReduced()。
单次调用/长期存在在纯 QML 应用中执行耗时计算,并在结果就绪时更新 GUI 。将计算代码放在 .js 脚本中,将它附加在 WorkerScript 实例上。调用 WorkerScript.sendMessage() 启动新线程执行计算。脚本也同样调用 sendMessage(),将结果传回 GUI 线程。在 onMessage 中处理结果并且更新 GUI 。
长期存在对象位于另一个线程中,可以根据请求执行不同的任务和/或接收要使用的新数据。子类化一个 QObject 以创建一个工作类。实例化这个工作类对象与一个 QThread 。将工作类移入新线程。通过队列信号槽的连接,将命令与数据传递给工作类对象。
长期存在在另一个不需要接收任何信号或事件的线程中,重复执行资源开销大的操作。直接重写 QThread::run() 并创建死循环。启动无事件循环的线程。可以发送信号将数据送回 GUI 线程(译者注:发送信号不需要依赖事件循环,接收并执行槽函数才需要)。

QMainWindow 类

QMainWindow 类用于创建主程序窗口。 更多内容...

属性方法
头文件:#include <QMainWindow>
qmake:QT += widgets
继承:QWidget

公共成员类型

类型方法
enumDockOption { AnimatedDocks, AllowNestedDocks, AllowTabbedDocks, ForceTabbedDocks, VerticalTabs, GroupedDragging }
flagsDockOptions

属性

属性名类型
animatedbool
dockNestingEnabledbool
dockOptionsDockOptions
documentModebool
iconSizeQSize
tabShapeQTabWidget::TabShape
toolButtonStyleQt::ToolButtonStyle
unifiedTitleAndToolBarOnMacbool

公共成员函数

返回类型函数名
QMainWindow (QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags())
virtual~QMainWindow ()
voidaddDockWidget (Qt::DockWidgetArea area, QDockWidget *dockwidget)
voidaddDockWidget (Qt::DockWidgetArea area, QDockWidget *dockwidget, Qt::Orientation orientation)
voidaddToolBar (Qt::ToolBarArea area, QToolBar *toolbar)
voidaddToolBar (QToolBar *toolbar)
QToolBar *addToolBar (const QString &title)
voidaddToolBarBreak (Qt::ToolBarArea area = Qt::TopToolBarArea)
QWidget *centralWidget () const
Qt::DockWidgetAreacorner (Qt::Corner corner) const
virtual QMenu *createPopupMenu ()
QMainWindow::DockOptionsdockOptions () const
Qt::DockWidgetAreadockWidgetArea (QDockWidget *dockwidget) const
booldocumentMode () const
QSizeiconSize () const
voidinsertToolBar (QToolBar *before, QToolBar *toolbar)
voidinsertToolBarBreak (QToolBar *before)
boolisAnimated () const
boolisDockNestingEnabled () const
QMenuBar *menuBar () const
QWidget *menuWidget () const
voidremoveDockWidget (QDockWidget *dockwidget)
voidremoveToolBar (QToolBar *toolbar)
voidremoveToolBarBreak (QToolBar *before)
voidresizeDocks (const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation orientation)
boolrestoreDockWidget (QDockWidget *dockwidget)
boolrestoreState (const QByteArray &state, int version = 0)
QByteArraysaveState (int version = 0) const
voidsetCentralWidget (QWidget *widget)
voidsetCorner (Qt::Corner corner, Qt::DockWidgetArea area)
voidsetDockOptions (QMainWindow::DockOptions options)
voidsetDocumentMode (bool enabled)
voidsetIconSize (const QSize &iconSize)
voidsetMenuBar (QMenuBar *menuBar)
voidsetMenuWidget (QWidget *menuBar)
voidsetStatusBar (QStatusBar *statusbar)
voidsetTabPosition (Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
voidsetTabShape (QTabWidget::TabShape tabShape)
voidsetToolButtonStyle (Qt::ToolButtonStyle toolButtonStyle)
voidsplitDockWidget (QDockWidget *first, QDockWidget *second, Qt::Orientation orientation)
QStatusBar *statusBar () const
QTabWidget::TabPositiontabPosition (Qt::DockWidgetArea area) const
QTabWidget::TabShapetabShape () const
QList<QDockWidget *>tabifiedDockWidgets (QDockWidget *dockwidget) const
voidtabifyDockWidget (QDockWidget *first, QDockWidget *second)
QWidget *takeCentralWidget ()
Qt::ToolBarAreatoolBarArea (QToolBar *toolbar) const
booltoolBarBreak (QToolBar *toolbar) const
Qt::ToolButtonStyletoolButtonStyle () const
boolunifiedTitleAndToolBarOnMac () const

公共槽

返回类型函数名
voidsetAnimated (bool enabled)
voidsetDockNestingEnabled (bool enabled)
voidsetUnifiedTitleAndToolBarOnMac (bool set)

信号

返回类型函数名
voidiconSizeChanged (const QSize &iconSize)
voidtabifiedDockWidgetActivated (QDockWidget *dockWidget)
voidtoolButtonStyleChanged (Qt::ToolButtonStyle toolButtonStyle)

保护成员函数

返回类型函数名
virtual voidcontextMenuEvent (QContextMenuEvent *event) override
virtual boolevent (QEvent *event) override

详细描述

Qt 主窗口框架

主窗口提供了一套创建应用程序用户界面的框架。 Qt 用QMainWindow相关类 来管理主窗口。QMainWindow已经定义了一个布局,可以往里添加一些 QToolBarQDockWidget,也可以添加一个 QMenuBar 和一个 QStatusBar。这个布局有一个中央区域,可以放任意部件。如下图所示:

main window layout

注意 主窗口必须设置中央部件。

创建主窗口组件

中央部件通常是标准 Qt 部件,如 QTextEditQGraphicsView,也可自定义部件。用setCentralWidget()来设置中央部件。

主窗口可以是单文档界面或多文档界面。 Qt 中设置 QMdiArea 为中央部件即创建了多文档界面。

下面举例说明主窗口可以添加的部件。

创建菜单

Qt 用 QMenu 类实现菜单,主窗口将其放在 QMenuBar。可以添加 QActionQMenu,一个QAction代表菜单中的一个条目。

menuBar()可以得到主窗口的菜单栏,用 QMenuBar::addMenu 添加菜单。

QMainWindow 默认有一个菜单栏,可以用setMenuBar()自定义一个新的菜单栏。如果不想用 QMenuBar ,也可以用setMenuWidget()来定制菜单栏。

创建菜单代码示例:

    void MainWindow::createMenus()
    {
        fileMenu = menuBar()->addMenu(tr("&File"));
        fileMenu->addAction(newAct);
        fileMenu->addAction(openAct);
        fileMenu->addAction(saveAct);
    }

createPopupMenu()可以创建弹出式菜单,它会在主窗口收到 context menu 事件时弹出。 停靠部件和菜单栏默认实现了右键菜单,可以重写createPopupMenu()创建自定义菜单。

创建工具栏

Qt 用 QToolBar 类实现工具栏,可以用addToolBar()添加工具栏到主窗口。

可以设置 Qt::ToolBarArea 来控制工具栏的初始位置。可以用addToolBarBreak()insertToolBarBreak()分割工具栏所在的区域,前者可使接下来添加的工具栏换至新的一行,后者添加了一个工具栏分隔符。用 QToolBar::setAllowedAreasQToolBar::setMovable 可以限制用户放工具栏的位置。

工具栏图标的尺寸可以用iconSize()获取,它是平台相关的。可以用setIconSize()设置固定尺寸。用setToolButtonStyle()可以修改工具栏图标外观。

创建工具栏代码示例:

    void MainWindow::createToolBars()
    {
        fileToolBar = addToolBar(tr("File"));
        fileToolBar->addAction(newAct);
    }

创建停靠部件

Qt 用 QDockWidget 类实现停靠部件。停靠部件即可以停靠在主窗口的窗口,可以用addDockWidget()添加停靠部件到主窗口。

可以设置 Qt::DockWidgetArea 来控制停靠部件的位置,有上、下、左、右四种。setCorner()可以让一个角落属于某个相邻的区域。默认情况下,一个区域只有一个停靠部件,用setDockNestingEnabled()可以使其能上下或者左右排列多个停靠部件。

两个停靠部件也可以堆叠在一起,然后使用 QTabBar 来选择应显示哪个部件。

创建并添加停靠部件到主窗口的代码示例:

    QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this);
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    dockWidget->setWidget(dockWidgetContents);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

状态栏

setStatusBar()可以设置状态栏,调用statusBar()会返回主窗口的状态栏。查看 QStatusBar 获取更多内容。

存储状态

QMainWindow 用saveState()保存布局,用restoreState()恢复布局。包括工具栏和停靠部件的位置和相对主窗口的尺寸。

另请参阅 QMenuBarQToolBarQStatusBar, QDockWidgetApplication ExampleDock Widgets ExampleMDI ExampleSDI ExampleMenus Example

成员变量文档

enum QMainWindow::DockOption flags QMainWindow::DockOptions

该枚举包含指定 QMainWindow 停靠行为的标志。

函数描述
QMainWindow::AnimatedDocks0x01animated 属性
QMainWindow::AllowNestedDocks0x02dockNestingEnabled 属性
QMainWindow::AllowTabbedDocks0x04允许形成下方有 tabBar 的重合部件
QMainWindow::ForceTabbedDocks0x08每个停靠区域都只包含一个选项卡式停靠部件。换句话说,停靠区域里不能上下或左右排列停靠部件。如果设置了此选项,则 AllowNestedDocks 不起作用。
QMainWindow::VerticalTabs0x10设置 tabBar 在竖直左方位置(默认在下方),包含了 AllowTabbedDocks。另请参阅 setTabPosition ()
QMainWindow::GroupedDragging0x20拖动停靠部件的标题栏时,将拖动所有和它在一起的停靠部件。包含了 AllowTabbedDocks 。在某些停靠部件有区域限制时会有问题。(该枚举值在 Qt 5.6 添加)

这些选项只是控制停靠部件将如何放入 QMainWindow,不会重新排列停靠部件。所以要先给停靠部件设置这些选项,再添加到主窗口。AnimatedDocks 和 VerticalTabs 选项例外,它们可以随后设置。

此枚举值在 Qt 4.3 引入和修改

DockOptions 是 QFlags<DockOption> 的 typedef。它存储 DockOption 值的 OR 组合。

属性文档

animated : bool

此属性表示是否对操作停靠部件和工具栏进行动画处理

当停靠部件或工具栏在主窗口拖动时,主窗口会显示它们将停靠在什么位置。设置此属性使 QMainWindow 在平滑动画中移动其内容。清除此属性会使它们啪地进入新位置。

默认情况,此属性是生效的。如果主窗口调整尺寸或重绘太慢,可能会无效。

设置此属性与使用 setDockOptions () 设置 AnimatedDocks 选项相同。

该属性在 Qt 4.2 引入

存取函数:

返回类型函数名
boolisAnimated() const
voidsetAnimated(bool enabled)

dockNestingEnabled : bool

此属性表示停靠部件是否可以嵌套。

如果此属性为false,停靠区域只能是水平的或垂直的一行。如果此属性为true,停靠区域所占的区域可以沿任意方向拆分以包含更多的停靠部件。

译者注:如果设为 true,两个 dock 可以上面一块,下面一块,显示在一个区域里,如果设为 false,则两个 dock 只能变成选项卡式占用一个区域。

只有在包含大量停靠部件的应用程序中,才需要停靠嵌套。它给用户更大的自由来组织主窗口。但是,当停靠部件拖过主窗口时,停靠嵌套会导致更加复杂和不太直观的行为。

设置此属性与使用 setDockOptions () 设置 AllowNestedDocks 选项相同。

该属性在 Qt 4.2 引入

存取函数:

返回类型函数名
boolisDockNestingEnabled() const
voidsetDockNestingEnabled(bool enabled)

dockOptions : DockOptions

此属性表示 QMainWindow 的停靠行为

默认值是 AnimatedDocks | AllowTabbedDocks

该属性在 Qt 4.3 引入

存取函数:

返回类型函数名
QMainWindow::DockOptionsdockOptions() const
voidsetDockOptions(QMainWindow::DockOptions options)

documentMode : bool

此属性决定选项卡式停靠部件的选项卡栏是否为文档模式。

默认为 false

该属性在 Qt 4.5 引入

存取函数:

返回类型函数名
booldocumentMode() const
voidsetDocumentMode(bool enabled)

另请参阅 QTabBar::documentMode

iconSize : QSize

主窗口工具栏图标的尺寸。

默认是 GUI 样式的默认工具栏图标大小。请注意,使用的图标必须至少具有此大小,因为图标只会缩小。

存取函数:

返回类型函数名
QSizeiconSize() const
voidsetIconSize(const QSize &iconSize)

tabShape : QTabWidget::TabShape

此属性表示选项卡式停靠部件的选项卡形状。

默认是 QTabWidget::Rounded

该属性在 Qt 4.5 引入

存取函数:

返回类型函数名
QTabWidget::TabShapetabShape() const
voidsetTabShape(QTabWidget::TabShape tabShape)

另请参阅 setTabPosition ()