QT:信号和槽02

典型实例

在主界面中创建一个对话框,在这个对话框中可以输入姓名、编号,当单击"确定"按钮时,关闭对话框,然后将输入的编号通过信号发射出去,最后在主界面中接收该信号并且显示编号数值






项目建立完成后,向项目中添加新文件,模板选择Qt分类中的"Qt设计器界面类"​,界面模板选择Dialog without Buttons,类名设置为MyDialog。



在mydialog.h文件中添加代码来声明一个信号:

c 复制代码
#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>
#include<string>
namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = nullptr);
    ~MyDialog();

private:
    Ui::MyDialog *ui;

signals:
    void dlgReturn(std::string, int);//声明信号
};

#endif // MYDIALOG_H

声明一个信号要使用signals关键字,在signals前面不能用public、private或protected等关键字,因为信号默认是public函数,可以从任何地方进行发射,但是建议只在声明该信号的类及其子类中发射该信号。信号只用声明,不需要也不能对它进行定义实现。还要注意,信号没有返回值,只能是void类型的。因为只有QObject类及其子类派生的类才能使用信号和槽机制,这里的MyDialog类继承自QDialog类,QDialog类又继承自QWidget类,QWidget类是QObject类的子类,所以这里可以使用信号和槽。另外,使用信号和槽还必须在类定义的最开始处添加Q_OBJECT宏。

双击mydialog.ui文件进入设计模式,在界面中添加一个Spin Box部件和一个Push Button部件换位一个lineEdit,将pushButton的显示文本修改为"确定"​。

SpinBox用于整数的显示与输入,一般显示为十进制,也可以显示二进制和十六进制的数,而且可以在显示框增加前缀和后缀

lineEdit 输入姓名使用

转到pushButton的单击信号clicked()对应的槽,更改如下。

c 复制代码
void MyDialog::on_pushButton_clicked()
{
    int index = ui->spinBox->value();
    std::string name = ui->lineEdit->text().toStdString();
    emit dlgReturn(name,index); //获取输入值
    qDebug() << " index :" <<  index << " name :" << name;
}

击"确定"按钮便可以获取spinBox部件中的数值,然后使用自定义的信号将其作为参数发射出去。发射一个信号要使用emit关键字,例如这里发射了dlgReturn()信号。

connect()函数的最后一个参数type表明了关联的方式,由Qt::ConnectionType枚举类型指定,其默认值是Qt::AutoConnection,还有其他几个选择,在MyDialog类中使用emit发射信号之后,就会立即执行槽,只有等槽执行完以后,才会执行emit语句后面的代码。这里可以将这个参数改为Qt::QueuedConnection,这样在执行完emit语句后便会立即执行其后面的代码,而不管槽是否已经执行,可以通过"应用程序输出"窗口的信息查看效果。

然后到widget.h文件中添加自定义槽的声明:

c 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<string>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

private slots:
    void showindex(const std::string& name, int index);
};
#endif // WIDGET_H

下面打开widget.ui文件,向界面上拖入一个Label部件,更改其文本为"用户信息:​"​。

然后进入widget.cpp文件中,添加头文件#include "mydialog.h",再在构造函数中添加如下代码。

c 复制代码
#include "widget.h"
#include "ui_widget.h"
#include "mydialog.h"
#include <QString>
#include <QDebug>
#include <String>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    MyDialog *dlg = new MyDialog(this);

    connect(dlg, SIGNAL(dlgReturn(const std::string&, int)),
            this, SLOT(showindex(const std::string&, int)));

    dlg->show();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::showindex(const std::string& name, int index)
{
    // 将std::string转换为QString
    QString qName = QString::fromStdString(name);
    ui->label_2->setText(tr("%1").arg(qName));
    ui->label_3->setText(tr("%1").arg(index));
    qDebug() << "name: " << name ;
    qDebug() << "index: " << index ;
}

这里创建了一个MyDialog实例dlg,并且使用Widget作为父部件。然后将MyDialog类的dlgReturn()信号与Widget类的showValue()槽进行关联。

升级一下

将dlg定义为类成员,实现的功能是点击后dlg会关闭

widget.cpp

c 复制代码
#include "widget.h"
#include "ui_widget.h"
#include "mydialog.h"
#include <QString>
#include <QDebug>
#include <String>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    Widget::showdlg();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::showdlg()
{
    dlg = new MyDialog(this);

    connect(dlg, SIGNAL(dlgReturn(const std::string&, int)),
            this, SLOT(showindex(const std::string&, int)));

    dlg->show();
}


void Widget::showindex(const std::string& name, int index)
{
    // 将std::string转换为QString
    QString qName = QString::fromStdString(name);
    ui->label_2->setText(tr("%1").arg(qName));
    ui->label_3->setText(tr("%1").arg(index));
    qDebug() << "name: " << name ;
    qDebug() << "index: " << index ;
    dlg->close();

}

widget.h

c 复制代码
#ifndef WIDGET_H
#define WIDGET_H
#include "mydialog.h"
#include <QWidget>
#include<string>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void showdlg();

private:
    Ui::Widget *ui;
    MyDialog *dlg;

private slots:
    void showindex(const std::string& name, int index);
};

#endif // WIDGET_H

总结

这里实现了自己定义类,自己声明信号,关联槽函数。

注意

●需要继承自QObject类或其子类。

●在类定义的最开始处私有部分添加Q_OBJECT宏。

●槽中参数的类型要和信号参数的类型相对应,且不能比信号的参数多。

●信号只用声明,没有定义,且返回值为void类型。

●connect()函数时,信号和槽的参数只能有类型,不能有变量名

●使用emit发射信号

connect()函数的使用方法

1、自动关联

2、常规使用

3、自己定义信号

2、lamda函数

cpp 复制代码
QObject::connect(sender, &Sender::signal, [=](){
    // 在这里编写需要执行的代码
});

参考

《零基础学Ot 6编程》

相关推荐
wjs20241 小时前
JavaScript 语句
开发语言
cmpxr_2 小时前
【C】局部变量和全局变量及同名情况
c语言·开发语言
小碗羊肉3 小时前
【从零开始学Java | 第三十一篇下】Stream流
java·开发语言
aq55356003 小时前
Laravel10.x重磅升级,新特性一览
android·java·开发语言
报错小能手4 小时前
ios开发方向——swift错误处理:do/try/catch、Result、throws
开发语言·学习·ios·swift
老歌老听老掉牙4 小时前
PyQt5+Qt Designer实战:可视化设计智能参数配置界面,告别手动布局时代!
python·qt
网域小星球4 小时前
C 语言从 0 入门(十七)|结构体指针 + 动态内存 + 文件综合实战
c语言·开发语言·文件操作·结构体指针·动态内存·综合项目
aq55356004 小时前
三大编程语言深度对比:C# vs 易语言 vs 汇编
开发语言·汇编·c#
独特的螺狮粉5 小时前
云隙一言:鸿蒙Flutter框架 实现的随机名言应用
开发语言·flutter·华为·架构·开源·harmonyos
光泽雨5 小时前
c# 文件编译的过程
开发语言·c#