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 中引用部分來源於我幾年前的筆記,無法溯源,在此感謝。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章