当前位置: 首页 > news >正文

QT信号槽使用

信号和槽的声明

在qt中,信号槽机制是用于qt对象间通信的机制。一个类要能构使用信号槽,必须继承子QObject类并添加Q_OBJECT宏:

#include <QObject>

class qt_demo : public QObject
{
    Q_OBJECT
public:
    explicit qt_demo(QObject *parent = nullptr);

public slots:
    void slot_recv_code(int code);

signals:
    void signal_recv_code(int code);
};

声明信号的关键字为signals,声明槽函数的关键字为slots,这些都是qt独有的关键字,这些关键字会被Qt的moc转换为标准的C++语句。

信号和槽的关系

  • 槽的参数的类型需要与信号参数的类型相对应,
  • 槽的参数不能多余信号的参数,因为若槽的参数更多,则多余的参数不能接收到信号传递过来的值,若在槽中使用了这些多余的无值的参数,就会产生错误。
  • 若信号的参数多余槽的参数,则多余的参数将被忽略。
  • 一个信号可以与多个槽关联,多个信号也可以与同一个槽关联,信号也可以关联到另一个信号上。
  • 若一个信号关联到多个槽时,则发射信号时,槽函数按照关联的顺序依次执行。
  • 若信号连接到另一个信号,则当第一个信号发射时,会立即发射第二个信号。

信号和槽的关联(连接)

信号和槽使用QObject类中的成员函数connect进行关联,该函数有多个重载版本,如下所示。
版本1

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

其中sender为信号发送对象,receiver为信号接收对象,signal和method为信号和槽的签名字符串,一般用SIGNAL和SLOT宏来转换,type为连接类型。

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

版本2

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

其中sender为信号发送对象,receiver为信号接收对象,signal和method为通过QMetaMethod获取到的元信息,type为连接类型。QMetaMethod是Qt提供的一个专门类型,可以用来获取一个对象成员函数的元数据。

QMetaMethod signalMethod = QMetaMethod::fromSignal(&MyWgtA::signalA);
int methodIndex = m_wgtB->metaObject()->indexOfMethod("onSlotB()");
// 防止找不到;
if (methodIndex != -1)
{
	QMetaMethod slotMethod = m_wgtB->metaObject()->method(methodIndex);
    connect(m_wgtA, signalMethod, m_wgtB, slotMethod);
}

版本3

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

重载版本,等价与connect(sender, signal, this, method, type).,就是将sender本身的信号和槽绑定。

版本4

template <typename PointerToMemberFunction> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)

其中sender为信号发送对象,receiver为信号接收对象,signal为slot为成员函数指针,分别指向信号和槽函数,type为连接类型。

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

版本5

template <typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)

sender为信号发送者,signal为成员信号指针,functor为函数或者仿函数。同时这里没有连接type参数,相当于信号发送后直接调用functor。

The signal must be a function declared as a signal in the header. The slot function can be any function or functor that can be connected to the signal. A function can be connected to a given signal if the signal has at least as many argument as the slot. A functor can be connected to a signal if they have exactly the same number of arguments. There must exist implicit conversion between the types of the corresponding arguments in the signal and the slot.

例子

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

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

版本6

template <typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

对于版本5多了context和type连接类型,这里context对象可以理解为代替reveicer对象的作用。

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

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

connect的连接类型

Qt::ConnectionType定义了信号和槽之间的连接类型:

ConstantValueDescription
Qt::AutoConnection0(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::DirectConnection1The slot is invoked immediately when the signal is emitted. The slot is executed in the signalling thread.
Qt::QueuedConnection2The 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::BlockingQueuedConnection3Same 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::UniqueConnection0x80This 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.

信号和槽的断开

静态方式1

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

Disconnects signal in object sender from method in object receiver. Returns true if the connection is successfully broken; otherwise returns false.

  • 断开对象的信号所连接的所有东西
disconnect(myObject, nullptr, nullptr, nullptr);
// 等价
myObject->disconnect();
  • 断开对象指定信号连接的所有东西
disconnect(myObject, SIGNAL(mySignal()), nullptr, nullptr);
// 等价
myObject->disconnect(SIGNAL(mySignal()));
  • 和指定接收者断连
disconnect(myObject, nullptr, myReceiver, nullptr);
// 等价
myObject->disconnect(myReceiver);

If signal is nullptr, it disconnects receiver and method from any signal. If not, only the specified signal is disconnected.

If receiver is nullptr, it disconnects anything connected to signal. If not, slots in objects other than receiver are not disconnected.

If method is nullptr, it disconnects anything that is connected to receiver. If not, only slots named method will be disconnected, and all other slots are left alone. The method must be nullptr if receiver is left out, so you cannot disconnect a specifically-named slot on all objects.

静态方式2

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

等价方式1

成员方式3

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

断开本对象的信号连接

// a、断开对象A所有信号的连接:
myObjectA->disconnect();

// b、断开对象A的信号signalA()所有的连接:
myObjectA->disconnect(SIGNAL(mySignal()));

// c、对象A与对象B断开所有信号连接:
myObjectA->disconnect(nullptr, myReceiverB, nullptr);

// d、对象A与对象B断开槽函数onSlotB()所有相关信号的连接::
myObjectA->disconnect(nullptr, myReceiverB, SLOT(onSlotB()));

成员方式4

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

断开本对象和reciever连接的信号

// a、对象A与对象B断开所有信号连接:
myObjectA->disconnect(myReceiverB)

// b、对象A与对象B断开槽函数onSlotB()所有相关信号的连接::
myObjectA->disconnect(myReceiverB, SLOT(onSlotB()));

静态方式5

bool QObject::disconnect(const QMetaObject::Connection &connection)

断开一个connection,该connection是之前connect的返回。

静态方式6

template <typename PointerToMemberFunction> bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)

与静态方法1类似

QObject::disconnect(lineEdit, &QLineEdit::textChanged,
                   label,  &QLabel::setText);

注意点

  1. 信号之间可以相互连接
  2. 一个信号可以连接多个信号/槽
  3. 一个槽可以被多个信号连接
  4. 如果一个信号连接多个信号/槽,那么绑定的信号/槽的触发顺序和连接建立顺序一致
  5. disconnect会断开所有符合的连接
  6. sender或者receiver一旦销毁,连接自动断开
  7. 信号和槽存在自动绑定,参考Qt 源码剖析 - 信号槽自动连接机制

参考

QObject::connect
QObject::disconnect
QMetaobject

相关文章:

  • 数据结构 之 【顺序表实现】(c语言实现)
  • Docker-技术架构演进之路
  • SpringBoot 整合 JPA
  • Redis多线程技术助力向量数据库性能飞跃
  • 图论 之 BFS
  • 【linux核心命令】
  • 【网络安全】从零开始的CTF生活
  • 酵母细胞壁市场报告:探索潜力无限的生物资源宝库
  • Windows 系统下,使用 PyTorch 的 DataLoader 时,如果 num_workers 参数设置为大于 0 的值,报错
  • HAL_UART_Receive和HAL_UARTEx_ReceiveToIdle用于UART通信接收的区别
  • 软考—系统架构设计(案例 | 论文)
  • MATLAB在数据分析和绘图中的应用:从基础到实践
  • 10GE 万兆SFP光模块型号(常用光模块收发光功率范围)
  • 1.11作业
  • 关于酒店旅游信息的数据采集API接口返回||包含参数说明
  • Redis-RDB
  • git上传 项目 把node_modules也上传至仓库了,在文件.gitignore 中忽略node_modules 依然不行
  • 【鸿蒙开发】第四十四章 Map Kit(地图服务)
  • DeepSeek04-导出导入模型文件
  • QT开发技术 【opencv图片裁剪,平均哈希相似度判断,以及获取游戏窗口图片】
  • 响应式网站代码/上海sem
  • 有什么好看的网站资源/永久免费客服系统
  • 网站建设存在风险/汕头seo关键词排名
  • 电影网站权重怎么做/windows优化大师有毒吗
  • wordpress 指定阅读/seo代码优化工具
  • 最新新闻热点大事件/西安seo代理