QT信号与槽实现方式

1、第一种实现方式

在QT开发工具UI界面先拖入按钮,然后鼠标右键拖入按钮,点击选中槽,在页面选着需要的信号,然后OK,随即将会跳转到类的.cpp文件,(这种UI+代码结合的方式,会自动去绑定信号与槽)。

2、第二种实现方法

纯代码实现

2.1、在类的构造文件中绑定信号与槽

cpp 复制代码
QObject::connect(sender,SIGNAL(signal()),receiver, SLOT(slot()));
                sender------发送信号的对象
                SIGNAL(signal())--------信号类型
                receiver-------接收者
                SLOT(slot())--------槽函数

2.2、类.h头文件声明槽函数

2.3、槽函数执行功能

2.4、报错解决

出现QObject::connect: Parentheses expected,这个错是我自己粗心,但也不得不吐槽下qt的不合理设计,connect时槽函数忘记加括号也可以编译通过,而且connect忘记加括号的槽函数是可以接收到信号的,因为我的槽函数里面打印的东西确实有输出。有点坑。

在类中使用信号/槽时一定要加Q_OBJECT宏,signal和slots的参数要一样

槽函数加(): connect(toTopLayerAction, SIGNAL(triggered()), this, SLOT(slotLayerTop())); // 正确

切记忘了():connect(toTopLayerAction, SIGNAL(triggered()), this, SLOT(slotLayerTop)); // 错误

3、第三种实现方法

3.1、使用Lambda表达式在构造函数中实现

cpp 复制代码
QObject::connect(sender,&Sender::signal, [=]() {/* lambda body */ });

4、第四种方式

Qt 5 中引入,允许使用函数指针直接 连接信号和槽,这种方式类型安全, 且可以利用IDE 的代码补全和错误检 查。

cpp 复制代码
QObject::connect(sender,&Sender::signal, receiver,&Receiver::slot);

4.1、在构造函数中实现

5、自定义信号与槽

在Qt 中,自定义信号与槽是实现对象间通信的一种机制。信号和槽是 Qt 对象通信的核心特性,使得一个 对象能够在发生某种事件时通知其他对象。自定义信号与槽的实现步骤如下:

  1. 定义信号 :在 Qt 中,信号是 signals 关键字声明的类成员函数。它们不需要实现,只需声明。例
    如:

    class MyClass : public QObject {
    Q_OBJECT
    public:
    MyClass();
    signals:
    void mySignal(int value);
    };

在上面的例子中, MyClass 有一个名为 mySignal 的信号,它带有一个整型参数。
定义槽 :槽可以是任何普通的成员函数,但通常在类定义中用 slots 关键字标识。槽 可以有返回类型, 也可以接受参数,但它们的参数类型需要与发出信号的参数类型匹配 。例如:

复制代码
class MyClass : public QObject {
    Q_OBJECT
public slots:
    void mySlot(int value);
};

在这个例子中,我们定义了一个名为 mySlot 的槽,它接收一个整型参数。
连接信号与槽:使用 QObject::connect 函数将信号与槽连接起来。当信号被发射时,连接到这个信号 的槽将被调用。

复制代码
MyClass *myObject = new MyClass();
connect(myObject, SIGNAL(mySignal(int)), myObject, SLOT(mySlot(int)));

这行代码连接了 myObject 的 mySignal 信号到同一个对象的 mySlot 槽。
发射信号:使用 emit 关键字发射信号。当信号被发射时,所有连接到这个信号的槽都会被调用。

复制代码
emit mySignal(123);

这将触发所有连接到 mySignal 的槽。
5.1、例1

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
//widget.cpp
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //连接槽  ,触发对象和接收都是自己
    QObject::connect(this ,SIGNAL(mysignal()) ,this ,SLOT(myslot()));
    QObject::connect( this ,SIGNAL(mysignalparams(int)) ,this ,SLOT(myslotparams(int)) );
    emit mysignal();        //触发信号
    emit mysignalparams(999);   //触发带参数的信号
}

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

void Widget::myslot()     //槽函数
{
    std::cout << "myslot" << std::endl;
}

void Widget::myslotparams(int value)
{
    std::cout << "myslotparams ," << value << std::endl;
    qDebug() << "This is value = " << value;
}
cpp 复制代码
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <iostream>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

signals:            //自定义信号
    void mysignal();
    void mysignalparams(int value);

public slots:       //自定义槽
    void myslot();
    void myslotparams(int value);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

执行结果

5.2、例2

创建两个类,比如**Sender** 和**Receiver** 。Sender类将发出信号,而Receiver类将接收并处理这个信号。

cpp 复制代码
// Sender.h  
#ifndef SENDER_H  
#define SENDER_H  
  
#include <QObject>  
  
class Sender : public QObject {  
    Q_OBJECT  
public:  
    explicit Sender(QObject *parent = nullptr);  
  
signals:      
    void mySignal();      //信号
  
public slots:  
    void emitSignal();  
};  
  
#endif // SENDER_H
cpp 复制代码
// Sender.cpp  
#include "Sender.h"  
  
Sender::Sender(QObject *parent) : QObject(parent) {  
}  
  
void Sender::emitSignal() {  
    emit mySignal();          //发送信号
}
cpp 复制代码
// Receiver.h  
#ifndef RECEIVER_H  
#define RECEIVER_H  
  
#include <QObject>  
#include <QDebug>  
  
class Receiver : public QObject {  
    Q_OBJECT  
public:  
    explicit Receiver(QObject *parent = nullptr);  
  
public slots:  
    void handleSignal();      //槽函数
};  
  
#endif // RECEIVER_H
cpp 复制代码
// Receiver.cpp  
#include "Receiver.h"  
  
Receiver::Receiver(QObject *parent) : QObject(parent) {  
}  
  
void Receiver::handleSignal() {  
    qDebug() << "Signal received!";  //槽函数
}
cpp 复制代码
// main.cpp  
#include <QCoreApplication>  
#include "Sender.h"  
#include "Receiver.h"  
  
int main(int argc, char *argv[]) {  
    QCoreApplication a(argc, argv);  
  
    Sender sender;  
    Receiver receiver;  
  
    //连接信号与槽
    QObject::connect(&sender, &Sender::mySignal, &receiver, &Receiver::handleSignal);  
  
    sender.emitSignal(); // 调用函数发送信号
  
    return a.exec();  
}

6、QDebug()

QDebug 是 Qt 框架中用于输出调试信息的一个类。它提供了一种方便的方式来输出文本到标准输出(通 常是控制台),这对于调试 Qt 应用程序非常有用。 QDebug 类可以与 Qt 的信号和槽机制一起使用,使 得在响应各种事件时能够输出有用的调试信息。
使用 QDebug 的一个典型方式是通过 qDebug() 函数,它返回一个 QDebug 对象。然后,可以使用流操 作符 << 来输出各种数据类型。例如:

cpp 复制代码
qDebug() << "This is a debug message";
int value = 10;
qDebug() << "The value is" << value;

当执行这些代码时,它们会在应用程序的控制台输出相应的文本。这对于检查程序的运行状态、变量的 值或者跟踪程序的执行流程非常有帮助。
还可以使用 qDebug() 来输出自定义类型,只要为这些类型提供了适当的输出操作符重载。此外, Qt 还 提供了 qInfo() , qWarning() , qCritical() 和 qFatal() 函数 ,用于输出不同级别的信息,分别用 于普通信息、警告、关键错误和致命错误。这有助于对日志信息进行级别划分,从而更好地控制输出内
容。

相关推荐
四维碎片2 小时前
【Qt】UDP跨平台调试工具
qt·学习·udp
踏过山河,踏过海3 小时前
【用ui文件做个简单工具的开发,为什么修改完ui后,程序重新编译运行后,GUI界面还是不变呢?】
qt·ui
向阳开的夏天4 小时前
麒麟V10源码编译QT5.6.3 (x86 & arm64)
开发语言·qt
打码的猿6 小时前
Qt对话框不锁死主程序的方法
开发语言·qt
小小码农Come on9 小时前
Qt Creator常用设置
qt
wkm95611 小时前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt
小小码农Come on13 小时前
QT开发环境安装
开发语言·qt
小小码农Come on13 小时前
QT内存管理
开发语言·qt
有理想的打工人14 小时前
QT的安装
qt
SilentSlot15 小时前
【QT-QML】8. 输入元素
qt·qml