QObject Class翻译

我认为学习Qt应该了解这个最基本的基类

文章目录

数都是需要重载的
注意:这个类中的函数都是线程安全的
//何为线程安全
// 参考何为线程安全

connect和disconnect函数的使用

connect(const QObject *sender, const char*signal, const QObject *reciver, const char *method, Qt::Connection Type type)

connect(const QObject *sender, const char *signal, const char *method, Qt::Connect Type type) const

connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
// PointerToMemberFunction: 

connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)


详细描述

QObject是Qt对象模型的核心,在这个核心中,最重要的一个函数是一个无缝的通信机制:信号和槽,你可以通过connect函数将一个信号和一个槽连接在一起,还可以使用disconnect函数将一个信号和一个槽断开连接,为了避免永不停止的通知圈可以使用blockSignals()函数来临时断开信号的连接,protected函数connectNotify()和disconnectNotify()函数使寻迹连接可以运行
QObject在一个对象树种来管理组织自己,当你使用一个QObject父类派生了一个QObject对象,这个对象将会自动的把自己添加到它父类的子类列表中,它的父类拥有它自己对象的所有权,它将会自动的通过析构函数删除自己的子类,你可以函数findChild()和findChildren()函数,通过名字和选项类型来找一个对象。
每一个独享都有一个objectName()并且它的类名可以根据metaObject()函数来找到这个类,你可以通过函数inherits()来查看是否这个对象类派生了另外一个类
当一个对象被删除后,将会发射destroyed()信号,可以通过悬挂QObject的参考来捕捉到这个信号
QObject可以通过event()函数来接受事件,并且可以过滤掉其他对象的事件,详细的描述可以查看installEventFilter()和eventFilter()函数,一个很方便的句柄childEvent(),可以通过重写该函数类捕捉到其他子事件。
最后,QObject提供了基本的Qt的时间类支持,可以看QTimer函数
你可以注意到Q_OBJECT宏强制存在于任何包含信号槽和其他属性的信号中,你也需要来运行Meta Object Compiler在源文件中,我们强烈建议在所有的QObject的子类中使用这个宏,不管他是否包含信号,槽以及其他的属性,因为不这样做的话有可能会导致意想不到的结果
所有的Qt的widgets函数都继承于QObject,一个方便的函数isWidgetType()函数返回这个对象是否是一个widget,这个函数的执行速度比qobject_cast<QWidget *>(obj)或者obj->inherits(“QWighet”)
一些对象,比如children()函数,返回一个OBjectList,数据类型为QList<QObject *>

线程相关

一个QObject实例是有一个线程相关的,或者可以说他运行在一个特sing的线程中,当一个QObject收到一个队列信号或者一个事件,槽函数或者事件句柄将会运行在线程中,这个QObject对象将存在在一个:
注意:如果一个QObject没有线程相关(就是thread()函数返回0),或者存在一个没有事件循环的线程中,然后它就不能接受到队列信号或者事件。
默认情况下,一个QObject存在于一个自己创造的线程中,一个对象的线程相关可以被thread()函数队列滑,然后可以通过moveToThread()函数来改变
所有的QObject一定存在于相同的线程中,并且作为他们的父类,通常来讲:

  • 如果两个类存在不同的线程中,setParent()函数将会失败
  • 当一个QObject对象移动到另一个线程中,所有的子类将会自动的移动过去
  • 如果一个QObject对象有一个父类,那么moveToThread()函数将对其操作失败
  • 如果QObject是由QThread::run()函数中创建的,那么它不能变成OThread()对象的子类,因为他们不存在与同一个线程中

注意:一个QObject’s的成员变量不会自动的成为它的子类,父类子类的关系一定需要被其他的指向改子类的构造函数所创建,或者通过调用setParent()函数来创建,如果没有这一步,对象的成员变量将会保留在它的旧的线程中,直到moveToThread()函数被调用

不要复制构造函数或者赋值运算符

QObject类永远没有一个复制构造函数或者赋值运算符,这是设计决定的,事实上,他们是被声明的,但是一个有宏Q_DISABLE_COPY()函数的private选项,事实上,所有的Qt的类都是QObject的衍生(直接的或者是间接的),使用这个宏类声明他们的复制构造函数和赋值运算符是私有的,原因可以看Qt Object Model页面
主要的结论是你应该使用一个指向QObject的指针(或者指向你的QObject子类)要不然你可能需要使用一个QObject的子类来作为参数,举个例子,没有复制构造函数,你不能使用QObject的子类作为一个值储存在一个容器类中,你一定要储存指针(不可以把类放到容器类中,不过可以将指针放在里面)

自动连接

Qt的标签对象系统提供了一个在QObject的子类和子类的子类之间的自动连接信号和槽的机制,一旦对象被适当的对象名来定义后,而且槽使用一个简单的名称转换后,这个连接可以通过函数QMetaObject::connectSlotsByName()函数在运行时间中被执行
用户接口编译器生成代码来环形这个函数,并且在Qt Designer中创建的窗体中使能自动连接的信号和槽,详细的可以看QtDesigner的描述

动态属性

从Qt4.1开始,在运行过程中,一个QObject实例可以动态的被添加或者移除,动态属性在编译的时候不一定被声明,在static阶段他们也可以提供相同的优势,他们也可以被同样的API所操作-使用property()函数来读,使用setProperty()函数来写
从Qt4.3开始,属性的动态添加开始被Qt Designer所支持,所有标准的窗体可以用户创造的空间可以被赋予动态的属性

国际化(!18n)

所有的QObject的子类都具备Qt的跨平台的特征,使应用程序编译成为不同的语言
为了确保文本在平台中可以相互传输,请务必使用tr()函数

关于属性

objectName:QString

这个函数是这个对象的名字
你可以使用findChild()函数和对象的名字来搜索对象,你可以使用setChildrens()函数来找到一系列对象

qDebug("MyClass::setPrecision():(%s) invalid precision %f", qPrintable(objectName()), newPrecision);

默认情况下,该函数包含一个空的字符串
访问方式:

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

信号

void objectNameChange(const QString &objectName)

注意:这是一个私有的信号,可以被用在信号槽的连接,但是不能被用户所发射

成员函数

QObject::QObject(QObject *parent = nullptr)

使用父对象构造一个构造函数
这个对象的父类可能被作为这个对象的拥有者来看待,进一步说,一个对话框是他的里面的按钮的父类
这个父类的析构函数执行的时候将会析构掉它所有的子类
设置这个父类为0构造函数。如果这个对象是一个窗体,那么这个函数将只包含窗口的top-level
注意:这个函数可以被QML的标签对象系统所执行,详细的请看Q_INVOKABLE

void QObject::deleteLater() [slot]

安排这个对象的删除工作
这个对象将在控制者的事件循环函数结束后被删除,如果这个函数在调用的时候事件循环并没有被执行(比如deleteLater()函数在这个对象的QCoreApplication::exec()函数执行前被调用),那么这个对象将会在事件循环开始的时候被删除,如果这个函数在事件循环听之后被调用,那么这个对象将不会被删除,从Qt 4.8开始,如果这个函数在一个没有事件循环的线程中的被调用,这个对象将会在线程结束的时候被销毁
注意:进入和离开一个事件循环(比如打开一个模态对话框)将不会指向延期删除,对于即将要删除的对象,控制者一定在此函数调用后返回到事件循环中,它不适用于事先的之前已经存在的事件循环仍然在运行时的对象的删除,Qt的事件循环将会在新的事件循环开始的时候结束这些对象。
注意:多次调用这个函数是安全的后面添加的这个函数运行将会从事件循环队列中所删除。

void QObject::destroyed(QObject *obj = nullptr) [signal]

这个信号在对象销毁对的时候立刻发射出来,在所有的QPointer的实例接受到这个信号,这个信号是不能被阻断的。
在这个信号发射后所有的这个对象的子类都会被立刻销毁

void Object::objectNameChanged(const QString &objectName) [signal]

在这个对象的名字被改变后会发射这个信号,这个新的对象的名字将会作为一个objectname被传递
注意:这个是一个私有的信号,可以被用在信号连接中,但是不能被用户来发射
注意:可以参考属性objectName

QObject::~QObject() [virutal]

销毁这个对象,包括这个对象的子类
所有的发射到这个对象以及这个对象法神的信号都会被自动的断开连接,同时任何在事件队列中添加到这个对象的事件都会被移除,通常来讲,一般的做法是使用deltetLater()函数来安全的删除这个对象,而不是直接删除它
警告:所有的子类都会被删除,如果有任何的对象正在运行或者在全局运行,这个程序就会立刻停止工作,我们不建议在父对象的外部保存子对象的指针,如果你仍然在做这样的事,可以在该对象销毁的时候发射destoryed()信号来删除外面的指针

bool QObject::blockSignal(bool block)

如果阻断成功,由这个对象发射的信号将会被阻断(比如,发射一个没有任何执行的信号),如果阻断没有成功,也不会发生任何的故障
返回值是之前的signalBolcked()函数的值
要注意的是及这个对象的信号被阻断了,它仍然被发射了
信号阻断的过程是没有缓冲区的

void QObject::childEvent(QChildEvent *event) [virtual protected]

这个事件循环句柄可以被子类所重写,然后可以用来接收子类的事件,这个事件在事件参数中传递
QEvent::ChildAdded和QEvent::ChildRemoved事件在子对象添加或者删除的时候被发射到改对象,大多数星狂下,你可以仅仅依赖子类成为一个QObject,或者如果isWidgetType()函数返回真,QWidget(这是因为,在添加子类的情况下,子类还没有完全的被构建,在删除子类的时候,子类还没有完全被析构)
QEvent::ChildPolished事件是当子对象被擦亮的时候传递给窗口的,或者当擦亮的子对象被添加的时候,如果你接收到一个子对象擦亮的事件,子类的构造函数通常已经完成了,然后,还没有结束,多重擦亮事件将会推迟到到窗口的构造函数执行的时候
对于每一个子窗口,当收到一个子类添加的事件,0,或者更多子类擦亮的事件,和一个子类移除的事件
在子对象添加后立刻被移除的时候,擦亮事件会被忽略,如果这个子类在构造和析构环节被多次擦亮,你将会收到多个来自同一个子对象的擦亮事件,每一次都带着一个不同的虚函数表

const QObjectList &QObject::children() const

返回一个子对象的列表,列表的格式为
typedef QList<QObject*> QObjectList;
先添加的子类是列表中的第一个,最后添加的子类是列表中的最后一个,再新添加对的子类添加到最后面

QMetaObject::Connect QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = AutoConnection) [static]

按照给定的格式,创建一个从信号对象到槽对象发射的连接,返回一个连接的句柄,后面可以通过此句柄来断开这个连接
举个例子:

QLabel *label = new QLabel;
QScrolBar *scrolBar = new QScrolBat;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int));

这个例子保证了这个标签经常会显示当前scrollbar的值,我们注意到,信号和槽的参数不含任何变量名,下面的例子将会报错

// WRONG
QObject::connect(scrolBar, SIGNAL(valueChanged(int calue)), label, SLOT(setNum(int value)));

一个信号也可以连接到另一个信号

class MyWidget : public QWidget
{
	Q_OBJECT

public:
	MyWidget();

signals:
	void buttonClicked();

private:
	QPushButton *myButton;
};

MyWidget::MyWidget()
{
	myButton = new QPushButton(this);
	connect(myButton, SIGNAL(clicked()), this, SIGNAL(buttonClicked()));
}

在这个例子中,MyWidget的构造函数从一个私有的成员变量中传递了一个信号,并且使之关联在MyWidget的名字下
一个信号可以连接到很多的槽和信号,很多信号可以连接到一个槽上
如果一个信号连接到一系列的槽函数中,当这个信号被发射的时候,这些槽函数将会按照一定的规则被激活。
这个函数返回一个QMetaObject::Connection,这代表着这个连接的句柄被成功的连接到这个信号和槽上,如果不能创建连接,那么这个连接句柄将会是无效的,举个例子,如果QObject不能来验证任何一个存在的信号和方法,或者他们的签名是不兼容的,你可以通过句柄转换为Bool来检查句柄是否有效
默认情况下,这个信号发射到你所设定的任何的连接上,两个信号如果从复制连接中发射,你可以使用一个信号disconnect()函数来销毁所有的连接,如果是通过Qt::UniqueConnect的类型来连接,不过不是副本的情况下这个连接将紧紧会被创建,如果这里已经存在了一个副本(精确的信号通向精确的对象的槽函数),这个连接练会失败,并且返回一个无效的QMeatObject::Connect
注意:Qt::UniqueConnect不是为lambdas而工作,没有成员的函数和函数,他们仅仅用用在连接到成员函数
可选连接参数类型定义了连接的建立,通常来讲,它定义了一一个特殊的信号是如何立刻连接到槽函数的,放在队列中等一下,如果这个信号是队列形式的,这个参数一定是Qt的元对象系统的已知的类型,因为Qt需要复制这个参数,还要在背后场景中来储存这个事件,如果你想使用队列连接的话,你讲得到故障的信息

QObject::connect: Cannot queue arguement of type 'MyType'

在建立这个连接之前,调用函数qRegisterMetaType()来登记这个数据类型

QMetaObject::Connect QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnect) [static]

按照给定的格式,创建一个从信号对象到槽函数对象的连接,返回一个连接句柄,这样的话可以在后面讲这个连接断开
如果不能构造一个连接的话,这个连接句柄是无效的,举个例子,这个参数是无效的话,你可以检查QMetaObject::Connection函数的有有效性
这个函数和上面的connect函数的用法是相同的,不同的地方是可以使用QMetaMethod来指定信号和方法

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

这个函数是上面第一个connec()函数的重载
将信号从发射对象连接到对象的方法
等价于connect(sender, signal, this, method, type)
对于每一个连接,都需要发射一个信号,同时复制的连接会发射两个信号,你可以使用disconnect()函数来断开一个连接
注意:这个函数是线程安全的

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

这个函数是上面第二个connect的重载函数
按照给定的了类型创建一个从发射对象到接收对象的连接,返回一个句柄,这样可以让用户后面可以断开连接
这个信号一定是在头文件中晟敏的一个函数,这个信号函数可以是任何的对象成员,这样可以连接到这个信号中,一个槽函数可以连接到给定的信号中,如果这个信号和很多和槽函数相同,信号和槽之间的类型存在着隐性转换。
比如

QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged, label, &QLabel::setText);

这个例子来确保这个标签和当前的Line edit中的问题一直是相同的
一个信号可以被连接到很多的槽函数和信号中,很多信号也可以连接大同一个槽函数
如果一个信号连接到了很多的槽函数中,则当信号发射的时候,插槽的连接顺序和创建的顺序相同
如果信号和槽正确的连接在一起后这个函数将返回一个句柄,如果创在连接失败,这个连接句柄将是一个无效值,举个例子,如果QObjec没有能力来验证一个信号是否存在(比如它并没有声明成为一个信号),您可以通过将QMetaObject::Connection转换为bool来检查它是否有效。
默认情况下,一个信号信号想发射给所有你创建的连接,如果有复制的连接的话,两个信号将被发射,你可以使用函数disconnect()函数来中断所有的连接,如果你使用了Qt::UniqueConnection的类型,这个连接将仅仅会在副本没有的时候才会创建,如果这里已经有一个副本(正确的相同的信号在同一个对象中连接到相同的槽函数中),这个连接将会失败并返回一个无效的QMetaObject::Connection对象
可选的参数类型
。。。。

QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor) [static]

这个函数是connect函数的重载函数
在发送对象和接收对象之间创在一个连接,并且返回这个连接的句柄
这个信号一定是在头文件中声明为一个信号,这个槽函数可以使任何连接到信号的函数,一个函数可以被给定的信号所连接如果这个信号拥有和槽函数相同的变量,函数子可以连接到一个信号,如果他们有相同的数量的变量,信号和槽之间的数据存在隐式转换
例子

void sonmeFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &PusButton::clicked, someFunction);

lambda表达式如下

QByteArray page = ...;
QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("qt-project.org", 80);
QObject::connect(socket, &TcpSocket::connect, [=] () {
	socket->write("GET " + page + "\r\n");
});

这个连接将会在发送者销毁的时候自动的断开连接,你应该关心任何使用functor的对象,在该信号发射的是否是否存在

QMetaObject::Connectcion QObject::connect(const QObject *sender, PointToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

这个函数是上面connect()函数的重载
按照给定的格式构建一个从发射对象到接收对象之间的连接,并返回这个连接的句柄
注意:Qt::UniqueConnections不会对lambdas工作,无参数的函数和算子,他们仅仅应用在连接到成员函数中
。。。省略之前的
例子:

void soneFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &PushButton::clicked, this, someFunction, Qt::QueuedConnect);

和前面的一样,但是让自己记住这几种用法

void QObject::connectNotify(const QMetaMethod &signal) [virtual protected]

这个虚函数在某些信号和槽连接在一起的时候被调用,如果你想比较信号和特殊的信号,你可以使用函数QMetaMethod::fromSIgnal()函数,例子如下:

if (signal == QMetaMethod::fromSignal (&MyObject::valueChanged)) 
{
	//signal is valueChanged
}

警告:这个函数违反了面向对象的原则,可以用但是代价有点大
警告:这个函数在执行到这个连接的时候被调用,可能和这个对象所在的线程不在同一个线程中

void QObject::custonEvent(QEvent *event) [virtual protected]

这个函数可以被子类所重载来接受定制的事件,定制的事件是用户定义的,使用Qt的枚举量QEvent::User和QEvent::Type枚举来定义连接的类型和值,这是一个特定的QEvent的子类,这个事件在事件参数中穿过

bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) [static]

断开信号发射的对象和信号接受信号之间的连接,如果成功的断开后将返回true,要不然就返回false,在对象被销毁的时候,涉及到信号和槽的断开
函数disconnect()可以使用3种方式来调用,下面是例子

  1. 断开一个对象的所有的信号的连接
disconnect(myObject, 0, 0, 0);

这个函数等价于非静态重载函数

myObject->disconnect();
  1. 断开一个对象中指定的信号
disconnect(myObject, SIGNAL(mySignal()), 0, 0);

等价于非静态重载函数

myObject->disconnect(SIGNAL(mySignal()));
  1. 断开一个指定的接受者
disconnect(myObject, 0, myReceiver, 0);

等价于非静态重载函数

myObject-<disconnect(myReceiver);

在这里,0 作为一种通配符,意味着"any signal", “any receiving object”, 或者"任何的在接受对象的槽函数", 等,发送者永远不会是nullptr(你不能再一次函数的调用中断开多个信号的的连接)
如果信号是0,这样从任何信号中断开接收者和方法,否者只能断开指定的信号和槽的连接。
如果接受者是0,这样断开任何连接喜好的连接,否则,对象中的槽函数会断开连接而不是接受者
如果方法是0,这将断开任何正在连接到接受者的信号,如果不这样的话,任何名为method的槽函数将会被断开连接,并且所有的其他的槽函数都会自己存在,如果不考虑接受者的话,这个方法必须是nullptr,因此你不能断开对象中指定名字的槽函数。

bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method) [static]

断开发射对象到接受对象的连接,如果成功就返回true,如果失败就返回false
(我认为关于元对象的信号和连接目前看来不是很重要,先知道有这么一个东西,需要的时候再回来看)

bool QObejct::disconnect(const char *signal = mullptr, const QObejct *receiver = nullptr, const char *method = nullptr) const

这个函数是一个重载函数
断开信号和槽的连接

bool QObejct::disconnect(const QObejct *receiver, const char *method = nullptr) const

这个函数是一个重载函数
断开信号和槽的连接

bool QObject::disconnect(const QMetaObject::Connection &connection) [static]

断开信号和槽的连接
如果这个连接是无效的,将什么都不做

bool QObject::disconnect(const QObject *sender, PointToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method) [static]

这个函数是disconnect()函数的重载函数
断开指定的发射对象到接收对象之间的连接,如果成功则返回true,如果失败则返回False,一个信号和槽的连接在对象销毁的时候会断开连接。
有三种方式来使用这个函数,如下

  1. 断开连击到该对象的信号的所有的连接
disconnect(myObject, 0, 0, 0);
  1. 断开指定信号的所有的连接
disconnect(myObject, &MyObject::mySignal(), 0, 0);
  1. 断开指定的接受者
disconnect(myObject, 0, myReceiver, 0);
  1. 断开指定的信号和槽的连接
QObject::disconnect(lineEdit, &QLineEdit::textChanged, label, &QLabel::setText);

在这里,0 作为一种通配符,意味着"any signal", “any receiving object”, 或者"任何的在接受对象的槽函数", 等,发送者永远不会是nullptr(你不能再一次函数的调用中断开多个信号的的连接)
如果信号是0,这样从任何信号中断开接收者和方法,否者只能断开指定的信号和槽的连接。
如果接受者是0,这样断开任何连接喜好的连接,否则,对象中的槽函数会断开连接而不是接受者
如果方法是0,这将断开任何正在连接到接受者的信号,如果不这样的话,任何名为method的槽函数将会被断开连接,并且所有的其他的槽函数都会自己存在,如果不考虑接受者的话,这个方法必须是nullptr,因此你不能断开对象中指定名字的槽函数。

void QObject::disconnectNotify(const QMetaMethod &signal) [virtual protected]

(关于元对象的函数先不看)

void QObject::dumpObjectInfo() const

关系信号连击的转存信息,这个函数会在debug窗口输出信息

void QObject::dumpObjectTree() const

关系子对象的崩溃信息的输出
QList QObject::dynamicPropertyNames() const
返回我们使用setProperty()函数动态添加的属性

bool QObject::event(Qevent *e) [virtual]

这个虚函数可以接受消息,如果这个事件被发现和执行的话,这个函数返回true
这个函数可以被子类所重写
确保为所有未处理的事件调用父事件类实现
例子:

class MyClass : public QWidget
{
	Q_OBJECT

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

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

bool QObject::eventFilter(QObject *watched, QEvent *event) [virtual]

如果这个被作为事件过滤器的话,就可以使用它来过滤掉事件
在重写这个函数的时候,如果你想忽略掉一些事件
举例:

class MainWindow : public QMainWindow
{
public:
	MainWindow();

protected:
	bool eventFilter(QObject *obj, QEvent *ev) override;

private:
	QTextEdit *textEdit;
};

MainWindow::MainWindow()
{
	textEdit = new QTextEdit;
	setCentralWidget(textEdit);

	textEdit->installEventFilter(this);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
	if (obj == textEdit) {
		if (event->type() == QEvent::KeyPress) {
			QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
			qDebug() << "Ate key press" << keyEvent->key();
			return true;
		} else {
			return false;
		}else {
			//pass the event on to ths parent class
			return QMainWindow::eventFilter(obj, event);
		}
	}
}

我们在这个例子中看到未处理过的事件通过了该类的事件循环函数,一旦这个类重写了eventFilter()函数,就可以在该函数中写过滤的函数
一些事件比如QEvent::ShortcutOverride一定会被尤其的接受,目的是阻止传播

T QObject::findChild(sonst QString &name = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const

如果这个这个子对象可以强制转换成格式T的话,就返回这个字对象,如果找不到这个子对象就返回nullptr,省略名字这个参数会导致匹配到所有的子对象参数,默认的搜索方式是规递,除非指定搜索方式为FindDirectChildrenOnly
如果有超过一个的参数匹配到了搜索,最直接的最原始的结果将会返回,如果有很多个最直接的最原始的值,就得使用findChildren()函数
这个例子返回一个子的QPushButton对象,名为“button1”,即使这个按钮不是父类的直接子类

QPushButton *button = parentWidget->findChild<QPushButton *>("button1");

这个例子返回一个QListWidget的子对象,从他的父对象中

QListWidget *list = parentWidget->findChild<QListWidget *>();

这个例子从父窗口中返回一个直接的子对象名为"button1"

QPushButton *button = parentWidget->findChild<QPushButton *>("button1", Qt::FindDirectChildrenOnly);

这个例子返回一个父窗口的子窗口,

QListWidget *list = parentWidget->findChild<QListWidget *>(QString(), Qt::FindDirectChildOnly);

QList QObject::findChildren(const QString &name = QString(), Qt::FindChildOptions options = Qt::FindchildrenRecursively) const

(先略过,返回上一个函数所有的匹配到的子对象)

QList QObject::findChildren(const QRegular Expression &re, Qt:;FindChildOptions options = Qt::FindChildrenRecursively) const

略过,使用正则表达式的方式来查找子对象

bool QObject::inherits(const char * className) const

如果一个类的实例继承类名或者是一个QObject的子类,则返回true,如果不是,则返回false
例子:

  QTimer *timer = new QTimer;         // QTimer inherits QObject
  timer->inherits("QTimer");          // returns true
  timer->inherits("QObject");         // returns true
  timer->inherits("QAbstractButton"); // returns false

  // QVBoxLayout inherits QObject and QLayoutItem
  QVBoxLayout *layout = new QVBoxLayout;
  layout->inherits("QObject");        // returns true
  layout->inherits("QLayoutItem");    // returns true (even though QLayoutItem is not a QObject)

void QObject::installEventFilter(QObject *filterObj)

安装在一个监控类上一个事件过滤
例:

monitoredObj->installEventFilter(filterObj);

这个事件过滤的类是一个类,然后可以接收所有的发送到这个对象的事件的事件,这个过滤器可以拦截发送到这个对象的类这个事件过滤对象依赖于eventFilter()函数,如果这个事件可以被过滤的话,那么这个函数将返回true(比如stopped),要不然则返回false
如果有很多的事件过滤器安装在同一个对象上,那么这个过滤器最终只激活1个
这是一个keyPressEnter的类的过滤器

class KeyPressEnter : public QObject
{
	Q_OBJECT
	...

protected:
	bool eventFilter(QObject *obj, QEvent *event) override;
};

bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
	if (event->type() == QEvent::KeyPress) {
		QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
		qDebug("Ate key press %d", keyEvent->ket());
		return true;
	}
	else {
		//stand event processing
		return QObject::eventFilter(obj, event);
	}
}

这是安装这个过滤器的方法

KeyPressEater *keyPressEater = new KeyPressEater(this)
QPushButton *pushButton = new QPushButton(this);
QLsitView *listView = new QListView(this);

pushButton->installEventFilter(keyPressEater);
listView->installEventFilter(keyPressEater);

警告:如果你在eventFilter()函数中删除了一个接收的对象,请确保返回了true,如果返回了false,Qt将会向删除的对象发送事件,这样的话有坑导致程序崩溃
注意:事件过滤器要和该对象在同一个线程中,如果不在同一线程中,那么这个函数将什么都不做,如果该对象和过滤器在不同的线程中,这个事件过滤器将不会起作用

bool QObject::isSignalConnect(const QMetaMethod &signal) const [protected]

如果这个信号至少连接到了一个接收者,将会返回真,要不然就返回false
signal一定是这个对象的一个信号成员,否则这个行为没有用

static const QMetaMethod valueChangedsignal = QMetaMethod::fromSignal(&MyObject::valueChanged);
if (isSignalConnected(valueChangedSIgnal)) {
	QbyteArray data;
	data = get_the_value();
	emit valueChanged(data);
}

根据上面的代码片段,你可以参照知道如何避免发射一个没有接收的信号

bool QObject::isWidgetType() const

如果这个对象是一个窗体,则返回真

bool QObject::isWindowType() const

如果对象是一个window,则返回真

void QObject::killTimer(int id)

杀死时间ID号
ID号是由函数startTimer()创建的

const QMetaObject *QObject::metaObject() const

返回一个该对象中指向元对象的指针
一个元对象包含了一个继承于QObject的类的信息,比如类名,超类名,属性,信号和槽等,每一个QObject的子类都包含Q_OBJECT宏,这样的话就会包含一个元对象
元对象信息是信号和槽机制所需要的,函数Inherits()同样使用原对象
如果你没有指向实例的指针但是还想去访类的元对象,你可以使用staticMetaObject
例子:

QObject *obj = new QPushButton;
obj->metaObject()->calssName();
QPushButton::staticMetaObject.calssName();

void QObejct::moveToThread(QThread *targetThread)

改变该对象以及他的子对象的线程,如果这个对象有父类的话,则不能一定改对象,每一个进程将会在目标线程中继续运行
为了移动一个对象到主线程中,使用QApplication::instance()函数来检索一个纸箱当前应用的指针,同时可以使用QAppliation::thread()函数来在应用程序的线程中运行的线程
例子:

myObject->moveToThread(QPaalciation::instance()->thread());

如果目标线程是空,所有的这个对象以及它的子对象的事件进程将会停止运行,他们不会存在在任何一个线程中
注意:所有在此对象中激活的事件都会被复位,Timers首先在当前的线程中停止,然后在新的线程中开始,
持续在不同的线程中移动对象都会导致事件时间会无限期的延长
一个QEvent::ThreadChange事件将会在线程改变的时候发送到改对象中,你可以操纵这个事件来执行任何的特殊的处理,需要注意的是任何新的由这个对象提供的事件都会在新的线程中进行操作,如果它是Nullptr,那么没有事件会执行在此对象中。
警告:这个函数是非线程安全的,当前的线程一定要和当前线程相关,换句话说,这个函数仅仅可以将一个对象从一个线程中推到另外一个线程中

QObject *Qbject::parent() const

返回指向父类的指针

QVariant QObejct::property(const char *name) const

返回这个对象的名字参数
如果没有该参数,返回值将是无效的
这些信息都是有这个对象的元对象来提供的

int QObejct::receiver(const char *sginal) const [protected]

返回信号所连接的数量
自动所有的槽函数和信号可以被看作接收者发发射者的时候,同样的连接可以被措辞创建,接收者的数量和发射者的连接的数量是相同的
当调用这个函数的时候,你可以使用SIGNAL()宏来通过一个特殊的信号

if (receivers(SIGNAL(valueChanged(QByteArray))) > 0 {
	QByteArray data;
	get_the_value(&data);
	emit valueChanged(data);
}

void QObject::removeEventFilter(QObejct *obj)

从这个对象中移除一个事件过滤器,如果没有安装任何的事件过滤器的话,这个请求函数将会被忽略
当这个对象被销毁的时候,所有的事件过滤器都会被自动的移除

QObject *QObejct::sender() const [protected]

返回一个指向发射该信号的对象的指针,如果在槽函数中来由信号触发调用,除非他返回mullptr,这个指针仅在对象线程上下文调用此函数的slot执行期间有效
如果发送者被销毁了后,将会返回一个无效的指针,或者这个槽函数从发送信号中所断开连接

int QObject::senderSignallndex() const [protexted]

返回调当前执行的槽函数的的信号的的元方法的索引
(应该用不到,先不翻译了)

void QObject::setParent(QObject *parent)

将这个对象设置一个父类

bool QObject::setProperty(const char *name, const QVariant &value)

设置这个对象的一个名称属性的值
如果这个函数是使用Q_PROPERTY宏来定义的,如果成功了则返回true,如果失败了则返回false,如果这个函数不是由Q_PROPERTY来定义的,这样的会啊就会在元对象中没有列表,所以需要作为动态属性添加在上面
(其他的不翻译了)

bool QObject::signalsBlocked() const

如果这个信号是封堵的,就返回true,要不就返回false

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)

开始一个时间并返回这个事件的ID,如果不能够开始这个事件就返回0
开始一个时间事件,在每间隔多少ms就调用一次,直到函数killTimer()调用之前,如果间隔是0,那么事件事件将会在每一个事件都会发生,操作系统就没有其他的精力来处理其他的事件了
虚函数timerEvent()会在QtimerEvent事件发生时调用,通过重写这个虚函数来得到时间事件
如果多个时间在运行,函数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); 
	startTimer(1000);
	startTimer(600000);

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

	// 从C++14开始可以在chrono中使用字符作为输入了
	startTimer(100ms);
	starttimer(5s);
	startTimer(2min);
	startTimer(1h);
}

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

注意:QTimer的性能是取决于当前操作系统和硬件能力的,timerType的螺距允许定制这个timer的能力,详细的可以看Qt::timerType来看不同的时间的类型,很多平台都支持20ms一次的性能,一些提供的更厉害,如果Qt不能驱动一定程度的时间事件,它将会默默的丢弃一些
QTimer类提供了一个高级别的编程接口,使用信号和槽的机制来代替事件的机制,还有一个QBasicTimer类,它比QTimer更轻量级,并且比直接使用计时器id更方便。

int QObject::startTimer(std::chrono::millisecond time, Qt::TimerType timertype = Qt::Coarse Timer)

这是一个重载的函数
开始时间并返回一个时间ID,如果不能开始一个时间,则返回0
一个时间事件将在每一个事件间隔触发,直到函数killTimer()被触发,如果事件和std::chrono::duration::zero()相同,则windows将会卡死
虚函数timerEvent()会在QtimerEvent事件发生时调用,通过重写这个虚函数来得到时间事件
如果多个时间在运行,函数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();
  }

注意:QTimer的性能是取决于当前操作系统和硬件能力的,timerType的螺距允许定制这个timer的能力,详细的可以看Qt::timerType来看不同的时间的类型,很多平台都支持20ms一次的性能,一些提供的更厉害,如果Qt不能驱动一定程度的时间事件,它将会默默的丢弃一些
QTimer类提供了一个高级别的编程接口,使用信号和槽的机制来代替事件的机制,还有一个QBasicTimer类,它比QTimer更轻量级,并且比直接使用计时器id更方便。

QThread *QObject::thread() const

返回这个对象存在线程

void QObject::timerEvent(QTimerEvent *event) [virtual protected]

这个事件句柄可以被子类所重写,用来接受时间事件并处理
QTimer类提供了一个更高级的时间功能的接口,同时还提供更通用的关于这个事件的信息,时间事件需要通过时间通道参数

QString QObject::tr(const char *sourceText, const char *disambiguation = Q_OBJECT, int n = Q_OBJECT) [static]

返回一个翻译过的源文本,可选地基于包含复数的字符串的消歧字符串和值n;默认将返回QString::fromUtf8(源文本),如果没有附加的可用的翻译的字符串
举个例子:

void MainWindow::createActions()
{
	QMeun *fileMeun = meunBar()->addMeun(tr("&File)");

(用这个函数写QString可以保证在不同的平台,不同的版本中不出现乱码)

const QmetaObject QObejct::staticMetaObject

(不翻译)
返回这个这个对象的元对象

相关的非成员对象

T QObject::qobject_cast(QObject *object)

T QObject::qobject_cast(const QObject *object)

一种强制转换的方式
比如:

  QObject *obj = new QTimer;          // QTimer inherits QObject

  QTimer *timer = qobject_cast<QTimer *>(obj);
  // timer == (QObject *)obj

  QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
  // button == 0

这个函数类似于C++中的标准库dynamic_cast()

typedef QObject::QObjectList

QList QObject::qFindChildren(const QObject *obj, const QRegExp &regExp)

宏文档

QObject::QT_NO_NARROWING_CONVERSIONS_IN_CONNECT

定义这个宏,将会禁用在信号和槽中的浮点型数据向整型数据的转换

QObject::Q_CLASSINFO(Name, Value)

这个宏指定了关于这个类的额外的信息,同样可以允许使用QObject::mataObject()函数,在Active Qt, Qt D-Bus and Qt QML.中,Qt会限制这个函数的使用
额外的信息是使用下面的格式
例子:

  class MyClass : public QObject
  {
      Q_OBJECT
      Q_CLASSINFO("Author", "Pierre Gendron")
      Q_CLASSINFO("URL", "http://www.my-organization.qc.ca")

  public:
      ...
  };

QObject::Q_DISABLE_COPY(Class)

禁止使用复制构造函数和赋值表达式对给定的类
一个QObejct的子类的实例不能作为一只普通的变量一样被复制和指派,而是作为唯一的ID,这意为这当你创在一个属于你自己的关于QObject的子类的时候(不管是间接还是直接),你都不能通过复制构造函数和赋值表达式来操作它,然而,它可能不足以简单的从你的类中忽略,

QObject::Q_DISABLE_COPY_MOVE(Class)

禁用复制构造函数

QObject::Q_DISABLE_MOVE(Class)

在给定的类中禁用移动构造函数的用法和移动指派构造函数的方法

QObject::Q_EMIT

使用这个宏来代替emit关键词来发射信号,当你想使用3rd party signal/slot mechanism
这个宏常用在当在.pro文件中添加no_keywords的时候

QObject::Q_ENUM(…)

这个宏允许一个包含元对象系统的枚举变量,他们一定要放在Q_OBJECT或者Q_GADGET宏的后面
举个例子:

QObject::Q_ENUM_NS(…)

这个宏使用meta-object系统登录一个枚举变量类型,它一定要防止在枚举常量声明以后,并且要有Q_NAMESPACE宏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值