Qt几乎所有的类都是从QObject直接或间接继承的,但是你真的了解QObject吗?下面先看看QObject在官方手册中的介绍。
QObject是所有Qt类的基类,是Qt对象模型的核心。该模型的核心功能是信号和槽的通信机制(有吐槽Qt信号和槽的,个人建议不要用Qt,因为这是它的核心功能)。
创建信号和槽的连接:connect()
销毁连接:disconnect();
临时阻止信号:blockSignals();
追踪连接:connectNotify()和disconnectNotify(),这两个函数第一次见,以后分析。
当使用另一个QObject作为父对象创建QObject时,将自动添加到父对象的children()列表中,父对象会在析构时自动删除子项。在父对象中可以使用findChild和findChildren来查找子项。
每个对象都有一个objectName();删除对象时,会触发destroy信号。
默认情况下,QObject位于创建它的线程中。可以使用thread()查询对象的线程关联,并使用moveToThread()进行更改。
所有QObject都必须与其父级位于同一个线程中。所以:
如果涉及的两个QObject存在于不同的线程中,则setParent()将失败。
当QObject移动到另一个线程时,它的所有子节点也将自动移动。
如果QObject具有父级,则moveToThread()将失败。
如果在QThread :: run()中创建了QObject ,它们就不能成为QThread对象的子节点,
因为QThread不存在于调用QThread :: run()的线程中。
QObject类中的所有函数都是可重入的。
属性只有一个:objectName,类型是QString
有一点注意,当控件的父对象为空时,这个控件就是一个顶层窗口控件。
当对象销毁时,所有和它相关的信号都回断开,相关的事件也会从事件队列中移除。建议使用deleteLater()来销毁对象,它比直接销毁delete更安全。
手册中有一个警告:删除所有子对象。如果这些对象中的任何一个在栈或全局上,则程序迟早会崩溃。
我的理解是:使用new在堆上分配空间来创建子对象,让父对象负责它的内存回收;如果要在栈上创建对象,就不要指定它的父对象,以免父对象回收了栈内存,导致崩溃。
不建议从父项外部保留指向子对象的指针。如果仍然这样做,则destroy()信号检测对象何时被销毁。
警告:等待传递挂起事件时删除QObject可能会导致崩溃。如果QObject存在于与当前正在执行的不同的线程中,则不能直接删除它。改为使用deleteLater(),这将导致事件循环在所有挂起事件传递给它之后删除该对象。
当参数block=true时,该对象的信号被阻塞,即信号发不出去;除了destroy()信号。
返回子对象列表,QObjectList的定义:typedef QList < QObject * > QObjectList ;
列表第一个子项是最初添加的,最后一个子项是最后添加的;
在QWidget中的子项会因为提升函数raised()和降低lowered(),导致子项在列表中的变化,提升后子项将成为列表的最后一个,降低后会成为列表中最后一个。
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)
将有关此对象的信号连接等的信息转储到调试输出。
返回使用setProperty()加载的属性列表。
此虚函数接收事件到对象,如果事件e被识别和处理,则应返回true 。可以重新实现event()函数以自定义对象的行为。
确保为所有未处理的事件调用父事件类实现。
如果此对象执行installEventFilter安装为watched对象的事件过滤器,则过滤事件。
在重新实现此函数时,如果要过滤掉事件,即停止进一步处理,则返回true; 否则返回false。
警告:如果在此函数中删除接收器对象,请确保返回true。否则,Qt会将事件转发给已删除的对象,程序可能会崩溃。
返回找到第一个子项或孙子项;
options取值:
Qt::FindDirectChildrenOnly:只在子项中查找;
Qt::FindChildrenRecursively:在所有项(包括孙子、重孙子等)中递归查找
如:返回parentWidget中名字为button1的QPushButton
QPushButton *button = parentWidget->findChild <QPushButton * >( "button1");
返回可以强制转换为T类型的给定name 的该对象的所有子项,如果没有找到,则返回空列表。
如:返回parentWidget中所有QPushButton子项:
QList<QPushButton *> allPButtons = parentWidget.findChildren<QPushButton *>();
上个函数的重载,可以使用正则表达来搜索子项。
判断一个类是不是继承子className
QTimer *timer = new QTimer; // QTimer 继承自 QObject
timer->inherits("QTimer"); // 返回 true
timer->inherits("QObject"); // 返回 true
timer->inherits("QAbstractButton"); // 返回 false
在此该类上安装事件过滤器,即filterObj监视该类的事件发生。
如果该类继承自QWidget,则返回true,该函数比inherits(“QWidget”)快
如果该类继承自QWindow,则返回true,该函数比inherits(“QWindow”)快
使用计时器标识id来终止计时器;该标识id是int QObject::startTimer返回的。
返回指向该对象的元对象的指针。
元对象包含有关继承QObject的类的信息,例如类名,超类名,属性,信号和槽。包含Q_OBJECT宏的每个QObject子类都具有一个元对象。
实例代码如下,如果类没有实例化过,可以使用staticMetaObject来获取元对象信息:
QObject *obj = new QPushButton;
obj->metaObject()->className(); // returns "QPushButton"
QPushButton::staticMetaObject.className(); // returns "QPushButton"
更改此对象及其子对象的线程关联。如果对象具有父对象,则无法移动该对象。事件处理将在targetThread中继续。
设置对象名,默认是空;该名字在findChild和findChildren,即查找子项中使用。
获取和设置父对象指针。
返回名字为name的属性值;
设置名字为name的属性值value;
阻止该对象发送信号,可以暂停发送信号,默认不阻止;
启动计时器并返回计时器标识符,如果无法启动计时器,则返回零。
启动后,每次超时将会触发 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();
}
返回对象所在的线程。
安全的删除对象,可以调用多次。
该信号在对象obj被销毁之前立即发出,并且不能signalsBlocked函数阻挡。
发出此信号后,所有对象的子项都会立即被销毁。
在更改对象名称后发出此信号。新对象名称作为objectName传递。
注意:这是一个private信号。它可以用于信号连接,但不能由用户发出。
大部分时虚函数,可以由用户来实现
可以重新实现子项事件处理,包括添加子项事件、删除子项事件
当连接信号时,触发该函数;
当断开信号时,触发该函数;
自定义事件
如果signal信号已经连接,则返回true
返回连接到signal的接收者的数量。
返回发送者指针;
当与发送者不在同一个线程中,并使用Qt::DirectConnection时,此函数无效。
(感觉上述话有问题,待测试)
不理解,请大神告知!
计时器事件
此宏将额外信息与类关联,该类可使用QObject::metaObject()获得。仅在Active Qt,Qt D-Bus和Qt QML中使用
禁用给定Class的复制构造函数和赋值运算符。
如果要将Qt信号和插槽与第三方信号/插槽机制一起使用,请使用此宏替换发射信号的关键字。
使用元对象系统注册枚举类型
此宏使用元对象系统注册枚举类型。它必须放在具有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
手机扫一扫
移动阅读更方便
你可能感兴趣的文章