Qt connect与信号槽

一 概述

  • Qt中一个十分主要的概念是信号槽,而使用信号槽必须要使用 QObject 类 的 connect函数。本文主要研究 connect函数,涉及以下方面;
    • connect 定义
    • connect 返回值
    • qRegisterMetaType
    • Q_DECLARE_METATYPE宏
    • Qt::ConnectionType
    • 信号槽三两点

二 connect 定义

  • 定义
static QMetaObject::Connection 
connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, 
        Qt::ConnectionType type = Qt::AutoConnection)(1)
static QMetaObject::Connection 
connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, 
        const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)(2)
QMetaObject::Connection 
connect(const QObject *sender, const char *signal, const char *method, 
        Qt::ConnectionType type = Qt::AutoConnection) const (3)
static QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, 
        PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)(4)
static QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)(5)
static QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context,
        Functor functor, Qt::ConnectionType type = Qt::AutoConnection)(6)
  • 信号槽几种连接写法
connect(myButton, SIGNAL(clicked()), this, SIGNAL(buttonClicked()));
---------------------
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged, label,  &QLabel::setText);
---------------------
void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);
--------------------- 
connect(socket, &QTcpSocket::connected, [=] () {
          socket->write("GET " + page + "\r\n");});

三 connect 返回值

  • connect 的返回值类型为 QMetaObject::Connection。
  • 官方文档

The function returns a QMetaObject::Connection that represents a handle to a connection if it successfully connects the signal to the slot. The connection handle will be invalid if it cannot create the connection, for example, if QObject is unable to verify the existence of either signal or method, or if their signatures aren’t compatible. You can check if the handle is valid by casting it to a bool.

  • 关于返回类型QMetaObject::Connection, 你可以直接用 bool 去接 connect 的返回值, 为 false 表示连接无效。举个栗子:connect 中信号名的大小写写错,并不会报错,但会返回false (抓狂过!)。
bool b = connect(myButton, SIGNAL(clicked()), this, SIGNAL(buttonClicked()));

四 qRegisterMetaType

  • 相关描述

call qRegisterMetaType() to register the data type before you establish the connection.

  • 在建立连接之前,使用qRegisterMetaType()注册自定义类型

Call qRegisterMetaType to register the type T. T must be declared with Q_DECLARE_METATYPE(). Returns the meta type Id.

  • 使用场景
    • 如果非 QMetaType 内置类型要在 Qt 的属性系统中使用。
    • 如果非 QMetaType 内置类型要在 queued connection 中使用。

With queued connections, the parameters must be of types that are known to Qt’s meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes.

int id = qRegisterMetaType<MyStruct>();

五 Q_DECLARE_METATYPE宏

  • 说明
    • 如果要使自定义类型或其他非QMetaType内置类型在QVaiant中使用,必须使用该宏。
    • 该自定义类型必须有公有的 构造、析构、复制构造 函数。
  • 两个例子(官方例子)
struct MyStruct
  {
      int i;
      ...
  };
Q_DECLARE_METATYPE(MyStruct)

 namespace MyNamespace
  {
      ...
  }

  Q_DECLARE_METATYPE(MyNamespace::MyStruct) // 有命名空间的写法

六 Qt::ConnectionType

  • connect的最后一个参数为 Qt::ConnectionType 类型,说明如下。
Constant Value Description
Qt::AutoConnection 0 (Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.
Qt::DirectConnection 1 The slot is invoked immediately when the signal is emitted. The slot is executed in the signalling thread.
Qt::QueuedConnection 2 The slot is invoked when control returns to the event loop of the receiver’s thread. The slot is executed in the receiver’s thread.
Qt::BlockingQueuedConnection 3 Same as Qt::QueuedConnection, except that the signalling thread blocks until the slot returns. This connection must not be used if the receiver lives in the signalling thread, or else the application will deadlock.
Qt::UniqueConnection 0x80 This is a flag that can be combined with any one of the above connection types, using a bitwise OR. When Qt::UniqueConnection is set, QObject::connect() will fail if the connection already exists (i.e. if the same signal is already connected to the same slot for the same pair of objects). This flag was introduced in Qt 4.6.
  • Qt::AutoConnection(自动方式) * Qt的默认连接方式,如果信号的发出和接收这个信号的对象同属一个线程,工作方式与直连方式相同;否则工作方式与排队方式相同。
  • Qt::DirectConnection(直连方式) * 当信号发出后,相应的槽函数将立即被调用。emit语句后的代码将在所有槽函数执行完毕后被执行。(信号与槽函数关系类似于函数调用,同步执行)
  • Qt::QueuedConnection(排队方式) * 当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。(此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行)
  • Qt::BlockingQueuedConnection(阻塞排队方式)
    • 与Qt::QueuedConnection相同, 只是信号所在线程在槽函数返回前阻塞。当信号与槽在同一线程时,禁止使用,否则发生死锁。
  • Qt::UniqueConnection(唯一连接标识)
    • 可以与以上任何一个连接类型以按位与方式组合。如果连接已存在,connect将失效。

七 信号槽三两点

  1. 在connect中,信号和槽函数参数不能包含变量名

Note that the signal and slots parameters must not contain any variable names, only the type. E.g. the following would not work and return false

// 错误
connect(scrollBar, SIGNAL(valueChanged(int value)), 
        label, SLOT(setNum(int value)));
  1. 一个信号也可以连接另一个信号

A signal can also be connected to another signal

  1. 一个信号可以连接多个信号和槽

A signal can be connected to many slots and signals.

  1. 多个信号可以连接到一个槽

Many signals can be connected to one slot.

  1. 如果一个信号连接到多个槽,槽被触发的顺序与连接顺序相同

If a signal is connected to several slots, the slots are activated in the same order in which the connections were made, when the signal is emitted.

  1. connect 和 disconnect 是线程安全的(thread-safe)
  2. 信号的参数个数不能少于槽函数。对应参数有隐式转化。

A slot can be connected to a given signal if the signal has at least as many arguments as the slot, and there is an implicit conversion between the types of the corresponding arguments in the signal and the slot.

八 说明

  • 参考
    • Qt doc
    • Qt::ConnectionType 中引用部分来源于我几年前的笔记,无法溯源,在此感谢。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章