当前位置: 首页 > news >正文

Qt源码分析: QChildEvent

本文记录QChildEvent事件相关代码分析。

注1:限于笔者研究水平,难免有表述不当,欢迎批评指正。

注2:博文会不定期更新,敬请关注。

一、QChildEvent的发送

分析QObject::setParent代码,当修改父对象时,便会旧parent发送QEvent::ChildRemoved事件;向新parent发送QEvent::ChildAdded事件。

/*!Makes the object a child of \a parent.\sa parent(), children()
*/
void QObject::setParent(QObject *parent)
{Q_D(QObject);Q_ASSERT(!d->isWidget);d->setParent_helper(parent);
}
void QObjectPrivate::setParent_helper(QObject *o)
{Q_Q(QObject);Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
#ifdef QT_DEBUGconst auto checkForParentChildLoops = qScopeGuard([&](){int depth = 0;auto p = parent;while (p) {if (++depth == CheckForParentChildLoopsWarnDepth) {qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; ""this is undefined behavior",q, q->metaObject()->className(), qPrintable(q->objectName()));}p = p->parent();}});
#endifif (o == parent)return;if (parent) {QObjectPrivate *parentD = parent->d_func();if (parentD->isDeletingChildren && wasDeleted&& parentD->currentChildBeingDeleted == q) {// don't do anything since QObjectPrivate::deleteChildren() already// cleared our entry in parentD->children.} else {const int index = parentD->children.indexOf(q);if (parentD->isDeletingChildren) {parentD->children[index] = 0;} else {parentD->children.removeAt(index);if (sendChildEvents && parentD->receiveChildEvents) {QChildEvent e(QEvent::ChildRemoved, q);QCoreApplication::sendEvent(parent, &e);}}}}parent = o;if (parent) {// object hierarchies are constrained to a single threadif (threadData != parent->d_func()->threadData) {qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");parent = 0;return;}parent->d_func()->children.append(q);if(sendChildEvents && parent->d_func()->receiveChildEvents) {if (!isWidget) {QChildEvent e(QEvent::ChildAdded, q);QCoreApplication::sendEvent(parent, &e);}}}if (!wasDeleted && !isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged)QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
}

因为QObject构造函数可以设置parent,此时发送QChildEvent事件,但对象并不一定创建完毕。

Refs. from QObject::childEvent(QChildEvent *)

QEvent::ChildAdded and QEvent::ChildRemoved events are sent to objects when children are added or removed. In both cases you can only rely on the child being a QObject, or if isWidgetType() returns true, a QWidget. (This is because, in the ChildAdded case, the child is not yet fully constructed, and in the ChildRemoved case it might have been destructed already).

二、应用案例

在SALOME中,SUIT_Desktop通过响应QChildEvent消息来讲SUIT_ViewWindow添加到SUIT_Desktop中。

class SUIT_Desktop::ReparentEvent : public QEvent
{
public:ReparentEvent( Type t, QObject* obj ) : QEvent( t ), myObj( obj ) {};QObject* object() const { return myObj; }private:QPointer<QObject> myObj;
};
/*!Child event.
*/
void SUIT_Desktop::childEvent( QChildEvent* e )
{if ( e->type() == QEvent::ChildAdded && e->child()->isWidgetType() ) {// The following line is a workaround to avoid showing view window as a top-level window// before re-parenting it to workstack (issue #23467).// See SUIT_ViewWindow::setVisible() and SUIT_Desktop::customEvent().e->child()->setProperty("blockShow", true );QApplication::postEvent( this, new ReparentEvent( QEvent::Type( Reparent ), e->child() ) );}else {QtxMainWindow::childEvent( e );}
}void SUIT_Desktop::customEvent( QEvent* e )
{if ( (int)e->type() != Reparent )return;ReparentEvent* re = (ReparentEvent*)e;SUIT_ViewWindow* wid = ::qobject_cast<SUIT_ViewWindow*>( re->object() );if ( wid ){bool invis = wid->testAttribute( Qt::WA_WState_ExplicitShowHide ) &&wid->testAttribute( Qt::WA_WState_Hidden );// The following line is a workaround to avoid showing view window as a top-level window// before re-parenting it to workstack (issue #23467).// See SUIT_ViewWindow::setVisible() and SUIT_Desktop::childEvent().wid->setProperty("blockShow", false);addWindow( wid );wid->setVisible( !invis );}
}

Refs. from QObject::customEvent(QEvent *event) 

This event handler can be reimplemented in a subclass to receive custom events. Custom events are user-defined events with a type value at least as large as the QEvent::User item of the QEvent::Type enum, and is typically a QEvent subclass. The event is passed in the event parameter. 

/*! Constructor.*/
SUIT_ViewWindow::SUIT_ViewWindow( SUIT_Desktop* theDesktop ): QMainWindow( theDesktop ), myManager( 0 ), myIsDropDown( true ), mySyncAction( 0 )
{myDesktop = theDesktop;setWindowIcon( myDesktop ? myDesktop->windowIcon() : QApplication::windowIcon() );setAttribute( Qt::WA_DeleteOnClose );myToolMgr = new QtxActionToolMgr( this );setProperty( "VectorsMode", false );
}

网络

QChildEventhttps://doc.qt.io/qt-6/qchildevent.html

QObject::childEvent(QChildEvent* event)https://doc.qt.io/qt-6/qobject.html#childEvent

QObject::customEvent(QEvent *event)https://doc.qt.io/qt-6/qobject.html#customEvent

SALOME源码分析:GUI模块https://blog.csdn.net/qq_26221775/article/details/127759145?spm=1001.2014.3001.5502

SALOME源码分析: GUI模块主要组件https://blog.csdn.net/qq_26221775/article/details/148845050?spm=1001.2014.3001.5502

http://www.lqws.cn/news/497791.html

相关文章:

  • Robyn高性能Web框架系列04:事件、中间件与错误处理
  • 异步IO框架io_uring实现TCP服务器
  • Postgresql中不同数据类型的长度限制
  • 用Python“看见未来”:自动驾驶感知系统实战全解析
  • 矩阵阶数(线性代数) vs. 张量维度(深度学习):线性代数与深度学习的基石辨析,再也不会被矩阵阶数给混淆了
  • react快速开始项目模板
  • 越南数学家吴宝珠恶搞式证明朗兰兹纲领
  • HTML基础结构
  • 速通KVM(云计算学习指南)
  • /var/lib/docker/overlay2目录过大怎么办
  • 深入浅出Node.js中间件机制
  • Android开发 原生设置-apps-里面隐藏应用信息
  • OpenSSL 混合加密
  • 企业级AI平台的能力架构与模块化规划
  • 大数据时代UI前端的变革:从静态展示到动态交互
  • TypeScript移动端导航工具实现
  • Arrays.asList和 List<String> list = new ArrayList<>();有什么区别
  • 飞算 JavaAI:重构 Java 开发范式的工程化实践
  • 可以把一套三维设计软件装在云服务器上5人同时并发使用吗
  • 通信网络编程3.0——JAVA
  • Deepoc大模型重构核工业智能基座:混合增强架构与安全增强决策技术​
  • Node.js 中的 JWT 认证:从生成到验证的完整指南
  • RPG38.角色受击
  • 配置@为src
  • React Native【实用教程】(含图标方案,常用第三库,动画,内置组件,内置Hooks,内置API,自定义组件,创建项目等)
  • Java并发编程中高效缓存设计的哲学
  • 实验九:RIPv2协议配置与分析
  • MySQL 8.x配置MGR高可用+ProxySQL读写分离(二):ProxySQL配置MySQL代理及读写分离
  • CRC3校验算法
  • Stable Diffusion 项目实战落地:AI绘画与文案创作的魔法 第一篇 ——让你的小说推文秒变视觉与故事双料爆款!