跳转至

信号槽

发出信号 - 执行信号连接的槽函数,就这么简单

注意:

  1. 一个信号发出后,会立即执行其连接的槽函数,等待槽函数执行完毕后,才会执行后面的代码

  2. 如果一个信号链接了多个槽,那么会等所有的槽函数执行完毕后才执行后面的代码,槽函数的执行顺序与连接顺序相同

信号

声明信号用 signals,发送信号用 emit

注意:

  1. 所有的信号声明都是 公共 的,所以 Qt 规定不能在 signals 前面加 publicprivateprotected

  2. 所有的信号都 没有返回值,所以返回值都用 void

  3. 所有的信号都不需要定义,在类中 声明即可

  4. 必须直接或间接继承自 QOBject 类,并且开头私有声明包含 Q_OBJECT

  5. 信号参数的个数不得少于槽参数的个数

声明槽用 public/protected/private slots:

不过如果使用下文提到的 QT5 的 connect() 函数来连接,那么任何函数(Lambda 表达式都可以)都可以作为槽函数,也就不需要用上面的声明了

连接

connect() 函数连接信号与槽,该函数有以下两种原型:

  1. QT4 、QT5 都能用

    static QMetaObject::Connection connect(
        const QObject *sender, // 信号发送对象指针
        const char *signal,    // 信号函数字符串,使用SIGNAL()
        const QObject *receiver, // 槽函数对象指针
        const char *member, // 槽函数字符串,使用SLOT()
        Qt::ConnectionType = Qt::AutoConnection// 连接类型,一般默认即可
    );
    
    // 按下按钮,触发 close() 槽函数
    connect(pushButton, SIGNAL(clicked()), dialog,  SLOT(close()));
    
  2. 仅用于 QT5

        static QMetaObject::Connection connect(
        const QObject *sender, //信号发送对象指针
        const QMetaMethod &signal,//信号函数地址
        const QObject *receiver, //槽函数对象指针
        const QMetaMethod &method,//槽函数地址
        Qt::ConnectionType type = Qt::AutoConnection//连接类型,一般默认即可
    );
    
    // 同上
    connect(pushButton, &QPushButton::clicked, dialog,  &QDialog::close);
    

其他

QSignalMapper

QSignalMapper 的核心在于 连接-配对-再发送

一个简单的例子:

Example

10 个按钮分别表示 0~9,要求按哪个按钮,QLineEdit 控件中同步显示按钮上对应的数字

连接:所有按钮的 clicked() 信号都连接到 signalMapper

配对:按钮与按钮上对应数字匹配

再发送:发送参数为按钮上对应数字的信号

SignalMapperWidget::SignalMapperWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SignalMapperWidget{
    ui->setupUi(this);
    // 创建垂直布局,将垂直布局作为主布局
    QVBoxLayout* vLayout = new QVBoxLayout(this);

    // 创建编辑框,用于显示点击按钮的文字,并且文字在右边显示
    QLineEdit* edit = new QLineEdit;
    edit->setAlignment(Qt::AlignRight);
    vLayout->addWidget(edit); // 将编辑框加入到垂直布局中

    // 创建信号匹配器
    QSignalMapper* signalMapper = new QSignalMapper(this);

    // 创建0-9数字键,并都加入到网格布局中
    QGridLayout *gridLayout = new QGridLayout;
    for (int i = 0; i < 10; ++i){
        QString txt = QString::number(i);
        QPushButton *button = new QPushButton(txt);
        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        signalMapper->setMapping(button, txt); // 将按钮和要发送的字符串配对
        gridLayout->addWidget(button, i / 3, i % 3); // 一行显示3列
    }

    // 连接配对信号和设置文字槽
    connect(signalMapper, SIGNAL(mapped(QString)),edit, SLOT(setText(QString)));

    vLayout->addLayout(gridLayout);
    resize(200, 200);
}

获取信号发送者

QObject* sender(); // 获取指向信号发送者的指针

解绑定信号槽

把连接函数中的 connect 改成 disconnect 即可

评论