QT信号和槽

本文详细解释了Qt框架中的信号与槽概念,包括它们如何在对象间通信,如何定义和连接信号与槽,以及QSignalMapper的使用。重点介绍了信号、槽的定义、连接方式和QSignalMapper的映射功能。
摘要由CSDN通过智能技术生成

信号和槽的概念

在Qt框架中,信号(Signal)和槽(Slot)是一种用于对象间通信的机制。它们被广泛应用于Qt的事件处理、用户界面和多线程编程等方面。

当用户或系统触发一个动作,导致某个控件状态发生了改变,该控件就会发射一个信号,即调用其类中一个特定的成员函数(信号),同时还可能携带有必要的参数

槽和普通的成员函数几乎没有什么区别,不在于其语法特性,而在于其功能,槽函数跟多体现为对某种特定信号的处理,可以将槽和其他对象信号建立连接,这样当发射信号时,槽函数将被触发和执行,进而完成具体的功能

信号

信号(Signal)是对象发出的消息,表示某个特定事件的发生。信号可以在任何地方定义,通常作为类的成员函数,使用 signals 关键字声明。例如:

class MyObject : public QObject
{
    Q_OBJECT

signals:
    void mySignal(int value);
};

MyObject 类定义了一个名为 mySignal 的信号,它带有一个整数参数。

槽(Slot)是用于响应信号的函数。槽可以在任何地方定义,通常也作为类的成员函数,使用 slots 关键字声明。例如:

class MyObject : public QObject
{
    Q_OBJECT

public slots:
    void mySlot(int value);
};

在这个例子中,MyObject 类定义了一个名为 mySlot 的槽函数,它接受一个整数参数。

信号和槽的连接

通过连接信号与槽,可以实现对象间的通信。连接可以使用 QObject::connect() 函数来建立,它的语法如下:

bool QObject::connect(const QObject *sender, const char *signal,
                      const QObject *receiver, const char *slot,
                      Qt::ConnectionType type = Qt::AutoConnection);

参数说明

  • sender 是发送信号的对象
  • signal 是信号的名称,可以使用SIGNAL(…)宏进行类型转换
  • receiver 是接收信号的对象
  • slot 是槽函数的名称,可以死使用SLOT(…)宏进行类型转换

例如,将 mySignal 信号连接到 mySlot 槽函数可以这样写:

MyObject *senderObj = new MyObject;
MyObject *receiverObj = new MyObject;

QObject::connect(senderObj, SIGNAL(mySignal(int)), receiverObj, SLOT(mySlot(int)));

当 senderObj 发出 mySignal 信号时,receiverObj 的 mySlot 槽函数将被调用,并传递相应的参数。

需要注意的是,在使用信号和槽机制之前,必须在类的声明中添加 Q_OBJECT 宏,以启用Qt的元对象系统。

信号和槽连接的语法要求:

  • 信号和槽的参数类型和数量必须匹配。例如,如果一个信号带有一个整数参数,那么连接的槽函数也必须带有一个整数参数
  • 信号和槽的名称必须正确。信号和槽的名称应该是字符串格式,例如 “clicked()”
  • 信号和槽的连接必须在运行时建立。这意味着,在连接信号和槽之前,必须先创建对象并分配内存,否则连接将无法建立
  • 信号和槽的连接必须使用 QObject::connect() 函数进行建立
  • 信号和槽的连接必须在类的声明中添加 Q_OBJECT 宏,以启用Qt的元对象系统。这个宏告诉Qt编译器,该类需要使用元对象系统支持的功能,例如信号和槽机制

connect的第五个参数

connect的第五个参数进行控制信号槽执行时所在的线程

  • 自动连接(AutoConnection),默认的连接方式,如果信号与槽,也就是发送者与接受者在同一线程,等同于直接连接;如果发送者与接收者处在不同线程,等同于队列连接。
  • 直接连接(DirectConnection),当信号发射时,槽函数立即直接调用。无论槽函数所属对象在哪个线程,槽函数总在发送者所在线程执行,即槽函数和信号发送者在同一线程
  • 队列连接(QueuedConnection),当信号发射时会被放入接收者对象的事件队列中,当控制权回到接受者所在线程的事件循环时,槽函数被调用。槽函数在接受者所在线程执行,即槽函数与信号接受者在同一线程

QSignalMapper

QSignalMapper是一个在Qt框架中用于信号映射的类。它允许您将多个发送者的信号映射到单个接收者的槽函数。这对于需要处理大量相似对象的情况非常有用。

使用QSignalMapper时,可以将不同对象的信号映射到QSignalMapper上的不同整数值或字符串值,然后将QSignalMapper的mapped()信号连接到接收者的槽函数。当发送者发出信号时,QSignalMapper会将该信号映射为先前设置的整数或字符串值,并发出mapped()信号,从而触发接收者的槽函数执行相应的操作。

常用函数:

//将特定发送者(sender)与整数(id)进行映射。当该发送者发出信号时,会将其映射为指定的整数值。
setMapping(QObject *sender, int id);

//将特定发送者(sender)与字符串(text)进行映射。当该发送者发出信号时,会将其映射为指定的字符串值。
setMapping(QObject *sender, const QString &text);

//手动触发信号映射器进行映射的操作。通常通过连接发送者的信号到信号映射器的map()槽函数来实现。
map();

//返回与特定发送者(sender)相关联的整数或字符串值。可用于查询特定发送者当前映射的值。
mapping(QObject *sender);

//移除特定发送者(sender)的所有映射。可以在需要清除特定发送者的映射时使用。
removeMappings(QObject *sender);

//清除所有映射,将信号映射器恢复到初始状态。
clearMapping();

代码示例:


#include <QtWidgets>

class MyWidget : public QWidget {
    Q_OBJECT
public:
    MyWidget(QWidget* parent = nullptr) : QWidget(parent) {
        QVBoxLayout* layout = new QVBoxLayout(this);

        QSignalMapper* signalMapper = new QSignalMapper(this);
        connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleButtonClicked(int)));

        for (int i = 0; i < 5; ++i) {
            QPushButton* button = new QPushButton(QString("Button %1").arg(i), this);
            layout->addWidget(button);
            
            // 将按钮的点击信号映射到整数值
            signalMapper->setMapping(button, i);
            
            // 连接按钮的点击信号到信号映射器的map()槽函数
            connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        }
    }

public slots:
    void handleButtonClicked(int buttonIndex) {
        qDebug() << "Button" << buttonIndex << "clicked";
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyWidget widget;
    widget.show();

    return app.exec();
}

#include "main.moc"

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值