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()的那个线程中。
bool QObject::blockSignals(bool block)
使用该函数,我们可以临时的阻塞一些信号。如果block为true,那么该对象发出的信号将被阻塞,也就是说发出的信号不会调用任何与它连接的槽函数。如果block为false,则取消阻塞。注意,destroyed()信号不会被阻塞。并且,信号阻塞期间所发出的信号不会被缓存。
void QObject::childEvent(QChildEvent *event)
子类可以重新实现这个事件处理器来处理子对象的添加和删除事件。除此之外,QEvent::ChildPolished事件会在子对象被抛光时或者被抛光的对象被添加到孩子列表中时发送。如果收到一个ChildPolished事件,那么该子对象的构造函数通常情况下已经完成了。但是,这是无法保证的,并且,在一个控件的构造过程中,可能产生多次ChildPolished事件。
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)
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 ®Exp, 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中继续进行。
int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)
void QObject::killTimer(int id)
void QObject::timerEvent(QTimerEvent *event)
开启一个定时器,并返回该定时器的标识符;或在不能开启定时器时返回0。