QObject

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

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

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

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

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

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

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


线程亲和性

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对象的成员变量会仍然存在于老线程中。

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

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

动态属性
从Qt4.2开始,就可以在运行时动态的从QObject对象上添加或移除属性。动态属性不需要在编译时进行声明,但它们提供了和静态属性一样的效率,并使用同一套API进行操作,即使用property()函数来读取属性值,使用setProperty()函数来修改属性值。
而从Qt4.3开始,Qt Designer也支持了动态属性,并且Qt的标准控件和用户自定义的控件都可以被赋予动态属性。

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

说了QObject的几个特性外,下面我们来看几个QObject类的重要的成员函数。
bool QObject::blockSignals(bool block)
使用该函数,我们可以临时的阻塞一些信号。如果block为true,那么该对象发出的信号将被阻塞,也就是说发出的信号不会调用任何与它连接的槽函数。如果block为false,则取消阻塞。注意,destroyed()信号不会被阻塞。并且,信号阻塞期间所发出的信号不会被缓存。

void QObject::childEvent(QChildEvent *event)
子类可以重新实现这个事件处理器来处理子对象的添加和删除事件。除此之外,QEvent::ChildPolished事件会在子对象被抛光时或者被抛光的对象被添加到孩子列表中时发送。如果收到一个ChildPolished事件,那么该子对象的构造函数通常情况下已经完成了。但是,这是无法保证的,并且,在一个控件的构造过程中,可能产生多次ChildPolished事件。
对每一个子控件,你会收到一个ChildAdded事件,0个或多个ChildPolished事件,一个ChildRemoved事件。

const QObjectList &QObject::children() const
返回一个孩子列表。并且,链表的顺序是按子对象添加的顺序排列的,第一个添加的子对象或控件在列表中的第一位,最后一个添加的在最后一位。也就是说,子对象或子控件是以append的形式追加的。
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
bool disconnect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method)
bool disconnect(const QMetaObject::Connection &connection)
bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
信号和槽进行连接和取消连接的函数。并且,一个信号可以连接到多个信号和槽上,通用,多个信号也可以连接到一个槽函数上。如果一个信号被连接到多个槽函数,当该信号被发送时,这些槽函数被调用的顺序和它们被连接的顺序一样。connect()函数如果调用成功,会返回一个QMetaObject::Connection对象,代表一个连接的句柄;如果调用失败,返回的连接句柄将是无效的。
默认情况下,一个信号会发送给每一个你生成的连接。可以使用disconnect()来打破所有的连接。
如果你向connect()函数中type参数传入一个Qt::UniqueConnection,那么,只有在当前不存在一个通用的连接时,即同一个对象将同一个信号连接到同一个槽函数,该调用才会成功。
最后一个可选的参数type,描述了连接的类型。特别情况下,它决定了一个特定的信号是立即被递送给一个槽函数,还是暂时排队,以后再递送。如果信号被排队了,那么信号携带的参数类型必须是Qt 元对象系统所认识的,因为,Qt在幕后会拷贝这些参数,并将其存储在一个事件对象中。
而对于disconnect()函数,可以传入0作为参数,意味着,“任何信号”,“任何接收对象”,“接收对象的任何槽函数”。
但sender不能传0。即不能再一次调用中取消多个对象的信号连接。
如果signal是0,即断开receiver和method再任何信号上的连接。如果非0,只断开特定的信号连接。
如果receiver是0,即断开到signal的所以连接。
如果method是0,即断开连接到receiver的任何东西

void QObject::deleteLater()
规划一个对象的释放。该对象会在程序控制返回到事件循环时被释放。如果当调用这个函数时,事件循环还为运行,比如,在QCorApplication()函数前调用该函数,那么该对象会在事件循环启动时被立即释放。如果该函数在主事件循环停止之后被调用,那么该对象将不会被释放。从Qt4.8开始,如果在一个对象上调用该函数,但该对象所在的线程没有运行事件循环,那么该对象会在线程结束时被销毁。
注意,进入和离开一个新的事件循环,比如打开一个模态对话框,不会执行延迟的释放操作;对于将要释放的对象来说,程序控制必须返回到调用该函数的事件循环中,才会被释放。
另外,在一个对象上多次调用该函数是安全的;因为当第一次被延迟的释放事件被递送之后,该对象的任何未决的事件都会从事件队列中删除。

bool QObject::event(QEvent *e)
可以重新实现该虚函数来自定义对象的行为。该函数接受发送给该对象的事件,并在事件被处理时返回true。对于所有我们自己不处理的事件,经过调用父类的实现。如:
  class MyClass : public QWidget
  {
      Q_OBJECT

  public:
      MyClass(QWidget *parent = 0);
      ~MyClass();

      bool event(QEvent* ev)
      {
          if (ev->type() == QEvent::PolishRequest) {
              // overwrite handling of PolishRequest if any
              doThings();
              return true;
          } else  if (ev->type() == QEvent::Show) {
              // complement handling of Show if any
              doThings2();
              QWidget::event(ev);
              return true;
          }
          // Make sure the rest of events are handled
          return QWidget::event(ev);
      }
  };

T QObject::findChild(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
QList<T> QObject::findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
QList<T> QObject::findChildren(const QRegExp &regExp, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
根据名字来查找子控件,如果不存在该控件,则返回0。如果忽略了name参数,则会匹配所有的对象。该搜索过程,默认是递归的,除非指明了FindDirectChildrenOnly选项。
如果存在多个匹配的对象,会返回直接祖先。如果有多个直接祖先,哪一个被返回将是未定义的。

void QObject::moveToThread(QThread *targetThread)
改变对象及其孩子的线程亲和性。但如果带对象有父,则无法移动。所有的事件处理会在targetThread中继续进行。
如果targetThread是0,那么该对象及其孩子的所以的事件处理会停止。
与该对象有关的所以获得定时器会被重置,即定时器先在当前线程中停止,再在targetThread中以同样的interval重新启动。所以,频繁的在不同线程间移动一个对象,会导致定时器事件延迟。
在线程亲和性改变之前,对象会收到一个QEvent::ThreadChange事件。我们可以处理该事件,进行一些特殊的操作。注意,递送给该对象的任何新事件都会在targetThread中进行处理。

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)
void QObject::killTimer(int id)
void QObject::timerEvent(QTimerEvent *event)
开启一个定时器,并返回该定时器的标识符;或在不能开启定时器时返回0。
成功开启定时器后,每隔interval,就会接收到一个TimerEvent事件,该事件又是由timerEvent()函数来处理。直到调用killTimer(),定时器停止。
如果interval是0,那么定时器事件会在没有其他窗口事件需要处理时才被递送。通过这个方式,可以实现一个空闲处理的功能。

当然,上面这些函数并不是QObject的全部内容,大家可以去Qt帮助文档中,浏览QObject的详细内容,包括我们此处没讲到的一些函数。另外,QObject中还有一些常用的宏定义,大都比较简单,大家可以自行研读。






  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Qt QObject 是 Qt 库中的一个基础类。它是所有 Qt 对象的基类,提供了许多基本的对象管理功能,包括内存管理、事件通信、信号和槽机制以及属性系统。 使用 QObject 的子类可以很容易地在应用程序中实现事件驱动的行为,并且可以利用 Qt 的信号和槽机制在对象之间进行通信。 例如,可以使用 QObject::connect 函数来连接一个对象的信号到另一个对象的槽函数,从而在信号发出时调用槽函数。这种机制可以让你很容易地在应用程序中实现事件驱动的行为,并且可以使用 Qt 的信号和槽机制在对象之间进行通信。 ### 回答2: Qt是一种跨平台的C++开发框架,用于构建图形界面和应用程序。QObject是Qt框架中的一个核心类,用于实现对象的即时信号和槽机制。 QObject提供了各种功能,例如对象的属性系统、线程支持、对象的生命周期管理等。在Qt中,所有类都继承自QObject或者其子类,以获得这些功能。 QObject的一个重要特性是信号和槽机制。信号和槽机制是一种对象间通信的方式,通过信号实现对象的某个事件的触发,然后通过槽函数来处理事件。信号和槽机制可以实现耦合度低、灵活性高的对象间通信,非常方便。 此外,QObject还有一个属性系统,用于管理对象的属性。属性可以是对象的状态或配置信息,可以通过属性系统实现对属性的读取和修改。属性系统提供了一种方便的方式来处理对象的状态变化或界面显示问题。 另外,QObject提供了对对象生命周期的管理。Qt中的对象可以是直接由new操作符动态创建的,也可以是作为父对象的子对象。当父对象删除时,它会自动删除其所有子对象,以避免内存泄漏问题。 总而言之,QObject是Qt框架中非常重要的一个类,提供了诸多功能,例如信号和槽机制、属性系统、对象生命周期管理等。它使得Qt开发更加方便和高效,极大地简化了开发人员的工作。 ### 回答3: Qt中的QObject是一个基类,用于构建具有对象管理和信号槽机制的应用程序。 QObject提供了一些重要的特性,使得Qt应用程序开发更加方便和灵活。首先,QObject提供了对象树的构造和管理能力。通过将QObject对象组织成树状结构,可以轻松地管理应用程序中的对象,包括对象的创建、销毁和层次关系等。这种对象树的管理机制使得QObject更适合构建大型复杂的应用程序。 QObject还提供了信号槽机制,用于实现对象之间的通信和交互。信号槽机制基于事件驱动的方式,当对象的某个状态发生变化或者执行某个操作时,会发出一个信号。其他对象可以通过连接到这个信号的槽函数来接收和处理这个信号。这种松耦合的通信方式使得应用程序的组件之间能够相互独立,易于维护和扩展。 QObject还提供了一些其他功能,包括动态属性的支持、线程安全的信号槽连接、对象的元对象信息等。动态属性功能允许在运行时为QObject对象添加自定义的属性,并且可以通过属性更改通知信号和属性读写方法进行访问。线程安全的信号槽连接确保多线程环境下信号槽的安全性和正确性。元对象信息允许在运行时获取对象的类型信息,包括类名、成员变量、方法等。 总之,Qt中的QObject是一个重要的基类,提供了对象管理和信号槽机制等核心功能,使得Qt应用程序开发更加简洁、灵活和可维护。它的使用可以大大提高应用程序的开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值