Qt QObject详解

这篇具有很好参考价值的文章主要介绍了Qt QObject详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 概述

QObject类是所以Qt类的基类,也是Qt对象模型的核心。这个模型中的核心特性就是能让对象键无缝通信的信号和槽的机制。我们可以使用connect()函数将一个信号连接到一个槽上,也可以使用disconnect()删除这个连接。为了防止无休止的的信号通知,还可以使用blockSignals()来临时阻塞信号。而connectNotify()和disconnectNotify()两个函数可以让我们能够跟踪一个对象上信号的连接变化。

QObject对象使用对象树的方式来组织它们自己。所以,当你以另一个对象作为父来创建一个QObject对象时,该对象会自动的将它自己添加的父级的孩子列表中,父级会接管该对象的所有权,也就是说,父级会在自己的析构函数中自动释放它的所有孩子。我们可以使用对象名通过findChild()或findChildren()函数在对象树中查找一个或多个对象。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

每一个QObject对象都有一个objectName(),并且它的类名也可以使用metaObject()对象来获取。还可以使用inherits()来判断一个对象所属的类是否继承自另一个类。

当一个对象被销毁时,它会发出destroyed()信号。我们可以捕捉该信号来做一些最后的处理。

QObject对象可以使用event()函数来处理事件,还可以通过installEventFilter()和eventFilter()函数来过滤或拦截其他对象的事件。QObject还支持基本的定时器。

注意,对于所有实现信号、槽、或者属性的QObject对象来说**,Q_OBJECT宏**都是必须的。我们推荐在每一个QObject的子类中使用这个宏,无论其是否实现信号、槽或属性,这可以避免一些奇怪的行为。

Qt中,所有的控件都派生自QObject。而QObject中的isWidgetType()函数可以判断一个对象是否是一个控件。

QObject所有的成员方法:

qt的qobject,QT开发,qt,ui,qt教程,qt开发,qt编程

 

2. 线程亲和性

QObject对象有一个线程亲和性,或者是它生存在某个特定的线程中。当一个QObject对象接收到一个queued signal或一个posted event时,相应的槽函数或事件处理器会在该对象所生存的线程中执行。

注意,如果一个线程没有线程亲和性,或者,如果它生存的线程没有运行事件循环,那么它不能接收到queued singal或posted event。

默认情况下,QObject对象生存在创建它的那个线程中。但我们可以使用thread()函数来查询对象的线程亲和性,还可以使用moveToThread()函数来改变一个对象的线程亲和性。并且,所有的对象都和它的父生存在同一个线程中。因此:

在调用setParent()时,如果涉及到的两个对象不在同一个线程,就会失败。

当一个QObject对象被移动到其他线程时,它们所有孩子也会自动被移动。

moveToThread()在对象有父级的时候,会失败

如果一个QObject对象是在QThread::run()中被创建的,那么它们不能成为QThread对象的孩子,因为QThread对象并不生存在调用QThread::run()的那个线程中。

注意,一个QObject对象的成员变量不会自动成为该对象的孩子。对象间的父子关系必须通过向子对象的构造函数传递一个指针,或通过调用setParent()来实现。如果没有这样做,那么,当调用moveToThread()时,QObject对象的成员变量会仍然存在于老线程中。

3. 没有拷贝构造函数或赋值运算符

QObject对象既 没有拷贝构造函数也没有赋值运算符。实际上,它们在QObject类中都进行了声明,只不过是放在了private区域,并使用了Q_DISABLE_COPY()宏进行了禁用。这样一来,你应该在需要QObject子类作为值的地方,使用一个QObject指针来代替。例如,因为没有拷贝构造函数,你不能将QObject对象作为值存储到容器类中, 必须使用指针来存储。

4. 自动连接

Qt的元对象系统提供了一个自动连接信号和槽的机制。只要对象定义了合适的对象名,并且相应的槽函数的声明遵循移动的命名约定,那么就会在运行时通过QMetaObject::connectSlotsByName()函数来自动进行信号和槽的连接。我们在之前的例子中,经常使用的“转到槽…”操作,就通过这种机制实现的。

5. 动态属性

从Qt4.2开始,就可以在运行时动态的从QObject对象上添加或移除属性。动态属性不需要在编译时进行声明,但它们提供了和静态属性一样的效率,并使用同一套API进行操作,即使用property()函数来读取属性值,使用setProperty()函数来修改属性值。

而从Qt4.3开始,Qt Designer也支持了动态属性,并且Qt的标准控件和用户自定义的控件都可以被赋予动态属性。

6. 国际化

所有QObject的子类都支持Qt的翻译特性,也使我们可以把应用程序的用户界面翻译成不同的语言。而为了使用户可见的文本可以被翻译,我们必须使用tr()函数来将这些文本包围起来。

7. 属性文档

属性只有一个:objectName,类型是QString

相关成员方法

 QString objectName() const
 void setObjectName(const QString &name)

8. 常用成员方法

QObject::QObject(QObject *parent = nullptr):构造函数
有一点注意,当控件的父对象为空时,这个控件就是一个顶层窗口控件。

QObject::~QObject():析构函数
当对象销毁时,所有和它相关的信号都回断开,相关的事件也会从事件队列中移除。建议使用deleteLater()来销毁对象,它比直接销毁delete更安全。
手册中有一个警告:删除所有子对象。如果这些对象中的任何一个在栈或全局上,则程序迟早会崩溃。
我的理解是:使用new在堆上分配空间来创建子对象,让父对象负责它的内存回收;如果要在栈上创建对象,就不要指定它的父对象,以免父对象回收了栈内存,导致崩溃。
不建议从父项外部保留指向子对象的指针。如果仍然这样做,则destroy()信号检测对象何时被销毁。

警告:等待传递挂起事件时删除QObject可能会导致崩溃。如果QObject存在于与当前正在执行的不同的线程中,则不能直接删除它。改为使用deleteLater(),这将导致事件循环在所有挂起事件传递给它之后删除该对象。 
    
bool QObject::blockSignals(bool block)
当参数block=true时,该对象的信号被阻塞,即信号发不出去;除了destroy()信号。    

const QObjectList&QObject :: children()const
返回子对象列表,QObjectList的定义:typedef QList < QObject * > QObjectList ;
列表第一个子项是最初添加的,最后一个子项是最后添加的;
在QWidget中的子项会因为提升函数raised()和降低lowered(),导致子项在列表中的变化,提升后子项将成为列表的最后一个,降低后会成为列表中最后一个。
    
connect函数组
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);

QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection);

QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const;

QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);

QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);

QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
    
disconnect
void QObject :: dumpObjectInfo() const
将有关此对象的信号连接等的信息转储到调试输出。

QList QObject::dynamicPropertyNames() const
返回使用setProperty()加载的属性列表。

bool QObject::event(QEvent *e) [virtual]
此虚函数接收事件到对象,如果事件e被识别和处理,则应返回true 。可以重新实现event()函数以自定义对象的行为。
确保为所有未处理的事件调用父事件类实现。
    
bool QObject::eventFilter(QObject *watched, QEvent *event) [virtual]
如果此对象执行installEventFilter安装为watched对象的事件过滤器,则过滤事件。
在重新实现此函数时,如果要过滤掉事件,即停止进一步处理,则返回true; 否则返回false。
警告:如果在此函数中删除接收器对象,请确保返回true。否则,Qt会将事件转发给已删除的对象,程序可能会崩溃。

T QObject::findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
返回找到第一个子项或孙子项;
options取值:
Qt::FindDirectChildrenOnly:只在子项中查找;
Qt::FindChildrenRecursively:在所有项(包括孙子、重孙子等)中递归查找

如:返回parentWidget中名字为button1的QPushButton
QPushButton *button = parentWidget->findChild<QPushButton *>("button1");

QList QObject::findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
返回可以强制转换为T类型的给定name 的该对象的所有子项,如果没有找到,则返回空列表。
如:返回parentWidget中所有QPushButton子项:
QList<QPushButton *> allPButtons = parentWidget.findChildren<QPushButton *>(); 

QList QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
上个函数的重载,可以使用正则表达来搜索子项。

bool QObject::inherits(const char *className) const
判断一个类是不是继承子className
QTimer *timer = new QTimer;         // QTimer 继承自 QObject
timer->inherits("QTimer");          // 返回 true
timer->inherits("QObject");         // 返回 true
timer->inherits("QAbstractButton"); // 返回 false    

void QObject::installEventFilter(QObject *filterObj)
在此该类上安装事件过滤器,即filterObj监视该类的事件发生。

bool QObject::isWidgetType() const
如果该类继承自QWidget,则返回true,该函数比inherits(“QWidget”)快

bool QObject::isWindowType() const
如果该类继承自QWindow,则返回true,该函数比inherits(“QWindow”)快

void QObject::killTimer(int id)
使用计时器标识id来终止计时器;该标识id是int QObject::startTimer返回的。

const QMetaObject *QObject::metaObject() const
返回指向该对象的元对象的指针。
元对象包含有关继承QObject的类的信息,例如类名,超类名,属性,信号和槽。包含Q_OBJECT宏的每个QObject子类都具有一个元对象。
实例代码如下,如果类没有实例化过,可以使用staticMetaObject来获取元对象信息:
QObject *obj = new QPushButton;
obj->metaObject()->className();             // returns "QPushButton"

QPushButton::staticMetaObject.className();  // returns "QPushButton"

void QObject::moveToThread(QThread *targetThread)
更改此对象及其子对象的线程关联。如果对象具有父对象,则无法移动该对象。事件处理将在targetThread中继续。

QString objectName() const 和 void setObjectName(const QString &name)
设置对象名,默认是空;该名字在findChild和findChildren,即查找子项中使用。

QObject *QObject::parent() const 和 void QObject::setParent(QObject *parent)
获取和设置父对象指针。

QVariant QObject::property(const char *name) const
返回名字为name的属性值;

bool QObject::setProperty(const char *name, const QVariant &value)
设置名字为name的属性值value;

bool QObject::signalsBlocked() const
阻止该对象发送信号,可以暂停发送信号,默认不阻止;

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)
启动计时器并返回计时器标识符,如果无法启动计时器,则返回零。
启动后,每次超时将会触发 timerEvent(QTimerEvent *event) 事件。
可以使用killTimer来终止计时。
当有多个计时器是,可以通过QTimerEvent::timerId() 获取计时器标识符来区别。
官方示例
class MyObject : public QObject
{
    Q_OBJECT

public:
    MyObject(QObject *parent = 0);

protected:
    void timerEvent(QTimerEvent *event) override;
};

MyObject::MyObject(QObject *parent)
    : QObject(parent)
{
    startTimer(50);     // 50-millisecond timer
    startTimer(1000);   // 1-second timer
    startTimer(60000);  // 1-minute timer

    using namespace std::chrono;
    startTimer(milliseconds(50));
    startTimer(seconds(1));
    startTimer(minutes(1));

    // since C++14 we can use std::chrono::duration literals, e.g.:
    //使用字面值
    startTimer(100ms);
    startTimer(5s);
    startTimer(2min);
    startTimer(1h);
}

void MyObject::timerEvent(QTimerEvent *event)
{
    qDebug() << "Timer ID:" << event->timerId();
}


QThread *QObject::thread() const
返回对象所在的线程。

公有槽函数

void QObject::deleteLater()
安全的删除对象,可以调用多次。

信号

void QObject::destroyed(QObject *obj = nullptr) [signal]
该信号在对象obj被销毁之前立即发出,并且不能signalsBlocked函数阻挡。
发出此信号后,所有对象的子项都会立即被销毁。

void QObject::objectNameChanged(const QString &objectName)
在更改对象名称后发出此信号。新对象名称作为objectName传递。
注意:这是一个private信号。它可以用于信号连接,但不能由用户发出。

受保护成员方法

大部分时虚函数,可以由用户来实现

void QObject :: childEvent(QChildEvent * event)[virtual protected]
可以重新实现子项事件处理,包括添加子项事件、删除子项事件

void QObject::connectNotify(const QMetaMethod &signal) [virtual protected]
当连接信号时,触发该函数;

void QObject::disconnectNotify(const QMetaMethod &signal) [virtual protected]
当断开信号时,触发该函数;

void QObject::customEvent(QEvent *event)
自定义事件

bool QObject::isSignalConnected(const QMetaMethod &signal) const
如果signal信号已经连接,则返回true

int QObject::receivers(const char *signal) const
返回连接到signal的接收者的数量。

QObject * QObject::sender() const
返回发送者指针;
当与发送者不在同一个线程中,并使用Qt::DirectConnection时,此函数无效。

int QObject::senderSignalIndex() const
发送信号索引

void QObject::timerEvent(QTimerEvent *event)
计时器事件

宏定义

QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
Q_CLASSINFO(Name, Value)
此宏将额外信息与类关联,该类可使用QObject::metaObject()获得。仅在Active Qt,Qt D-Bus和Qt QML中使用

Q_DISABLE_COPY(Class)
禁用给定Class的复制构造函数和赋值运算符。

Q_EMIT
如果要将Qt信号和插槽与第三方信号/插槽机制一起使用,请使用此宏替换发射信号的关键字。

Q_ENUM( …)
使用元对象系统注册枚举类型

Q_ENUM_NS( …)
此宏使用元对象系统注册枚举类型。它必须放在具有Q_NAMESPACE宏的命名空间中的枚举声明之后。它与Q_ENUM相同,但在命名空间中。
Q_FLAG( …)
Q_FLAG_NS( …)
Q_GADGET
Q_INTERFACES( …)
Q_INVOKABLE
Q_NAMESPACE
Q_OBJECT
Q_PROPERTY( …)
Q_REVISION
Q_SET_OBJECT_NAME(Object)
Q_SIGNAL
Q_SIGNALS
Q_SLOT
Q_SLOTS

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓文章来源地址https://www.toymoban.com/news/detail-597360.html

到了这里,关于Qt QObject详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Threads and QObjects,Thread-Support in Qt Modules】线程和QObjects,Qt模块中的线程支持

    Threads 继承了 QObjects类。它发出信号来指示线程已开始执行或已完成执行,并提供一些槽函数。 更有趣的是,QObjects可以在多个线程中使用,发出调用其他线程中槽的信号,并将事件发布到“live”在其他线程中的对象。这是可能的,因为每个线程都允许有自己的事件循环。

    2024年02月04日
    浏览(50)
  • 【Qt UI】QT 窗口/控件置顶方法详解

    在QT开发中,有时候我们需要让某个窗口或控件始终显示在其他窗口之上。这种需求在多窗口应用或者弹出提示框等场景中非常常见。本文将详细介绍如何在QT5和QT6中实现这一功能,并对两者之间的差异进行深入分析。 使用 Qt::WindowStaysOnTopHint 标志 在QT5中,最常用的窗口置顶

    2024年02月05日
    浏览(50)
  • [编程语言][C++][Qt]单独添加UI文件

    不知什么原因,Qt Creator并不是很完美很智能。当先写好界面类的头文件和源代码文件后,我们再添加用于可视化界面设计的UI文件时,会出现一些问题。 当使用CMake管理项目时,CMake会读取 CMakeLists.txt 文件来确定各种项目设置。需要把 MainWindow.ui 包含进项目时,在 CMakeLists.

    2024年02月07日
    浏览(46)
  • 【Qt 学习笔记】Qt 开发环境的搭建 | Qt 安装教程

    博客主页:Duck Bro 博客主页 系列专栏:Qt 专栏 关注博主,后期持续更新系列文章 如果有错误感谢请大家批评指出,及时修改 感谢大家点赞👍收藏⭐评论✍ 文章编号:Qt 学习笔记 / 02 1. 安装包下载(网盘链接) 链接:https://pan.baidu.com/s/1t3jbYcFYFuJIfe0hPmeDmQ?pwd=duck 提取码:du

    2024年04月26日
    浏览(99)
  • 【Qt】使用Qt designer(Qt设计师)以及uic工具将ui文件转换到C++代码进行界面开发

    【Qt】编写第一个Qt程序,使用Cmake编译并运行 Qt Designer是一个用于创建Qt应用程序用户界面的图形化界面设计器。它是Python GUI开发的一个重要工具,可以帮助用户快速创建具有丰富功能的用户界面。 打开终端输入以下代码 点击创建 拖一些组件进来,点击保存 得到一个后缀为

    2024年02月16日
    浏览(54)
  • 【Qt】Qt5.12.12安装教程详解

    Qt(官方发音 [kju:t],音同 cute)是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序,当然也可以开发不带界面的命令行(Command User Interface,CUI)程序。 Qt 是纯 C++ 开发的,所以学好 C++ 非常有必要,对于不了解 C++ 的读者,我建议先阅读《

    2024年02月13日
    浏览(40)
  • 【嵌入式Qt开发入门】Qt如何网络编程——获取本机的网络信息

            Qt 网络模块为我们提供了编写TCP/IP客户端和服务器的类。它提供了较低级别的类,例如代表低级网络概念的 QTcpSocket,QTcpServer 和 QUdpSocket,以及诸如 QNetworkRequest, QNetworkReply 和 QNetworkAccessManager 之类的高级类来执行使用通用协议的网络操作。它 还提供了诸如QNet

    2024年02月16日
    浏览(57)
  • Python QT5设计UI界面教程

    简介:PyQT5开发常用知识,零基础上手,需配合我之前写的博文,配置好QT设计工具和ui文件转py文件的工具。博文为:使用Python PyQt5实现一个简单的图像识别软件;页面效果如下: 1.设计菜单栏 Containers——Tab Widget; 2.横向排布  可以自动水平对齐 3.文本框和选择框 4.日期输入

    2024年01月17日
    浏览(47)
  • 【QT开发(5)】0919-QT里面新增ui类,新增使用opencv读取图片的普通类,在ui类中显示图片

    1、Qt Creator快速入门_第三版__霍亚飞编著 2、《Qt+OpenCV显示图片(Mat转QImage然后显示在QLabel上)》 https://gitee.com/hiyanyx/qt5.14-cpp_-empty_-project/tree/Study2023-section5/ git分支“Study2023-section5” 新增ui类 新增使用opencv读取图片的普通类 为了更加方便,可在QT 中添加普通类,这样会自动生

    2024年02月07日
    浏览(47)
  • QT 之基础(一) 详解UI文件设计与运行机制

    一、项目文件组成 1.1 创建一个项目文件        建立好项目如下   (1)项目组织文件【untitled.pro】 存储项目设置文件 (2)主程序入口文件【main.cpp】 实现函数main()函数程序文件   (3)窗体界面文件【mainwindow.ui】 一个XML格式存储的窗体上的元件及其布局文件。 任何界面窗

    2024年02月16日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包