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编程》

相关推荐
ZWZhangYu1 分钟前
【Arthas命令实践】heapdump实现原理
java·开发语言·python
vegetablesssss1 分钟前
使用QGraphicsProxyWidget将widget绘制在QGraphicsView中
qt
CyberScriptor16 分钟前
Swift语言的正则表达式
开发语言·后端·golang
土了个豆子的20 分钟前
线性表的接口定义及使用
开发语言·数据结构·数据库
孙尚香蕉24 分钟前
MapReduce经典案例-词频统计。
java·开发语言
Code侠客行41 分钟前
Perl语言的循环实现
开发语言·后端·golang
Quantum&Coder1 小时前
MATLAB语言的数据库交互
开发语言·后端·golang
网络空间站1 小时前
MATLAB语言的软件工程
开发语言·后端·golang
C++小厨神1 小时前
Rust语言的循环实现
开发语言·后端·golang
感谢地心引力1 小时前
【MATLAB】绘制投资组合的有效前沿
开发语言·matlab·金融·股票·有效前沿