matlab有信号与槽机制么,笔记:Qt5中的信号与槽,不要再用SIGNAL,SLOT了

这篇博客介绍了在Qt5.9中如何处理信号和槽的重载问题,强调了当信号被重载时,需要使用函数指针明确指定要连接的信号版本。作者通过一个实际例子展示了如何创建两个窗口,点击每个窗口的按钮来切换窗口的显示状态,同时自定义了重载信号并成功连接了槽函数。博客还指出了书上关于这个问题的解释不够清晰,作者提供了自己的理解和解决方案。
摘要由CSDN通过智能技术生成

看的书是Qt5.9,但书上却用的Qt4中的通用用法:SIGNAL和SLOT宏,

f60685d71b3f3b0bc76f8cfc88f3b2d3.png

不过,书后面却又给了一种传递信号和槽函数地址的用法(Qt5的用法),但是这本书的作者在这块却说的不好,如下图:

ac572a16acb8f60dd011e47c72261dc7.png

首先要知道,信号也是一个函数,它也可以像一般的函数一样进行重载。

1.没有对信号进行重载时,可以直接这样用,因为就这一个信号函数,不存在二义性的问题,即编译器不用纠结传入的到底是哪个函数的地址。

2. 但是当我们对信号进行重载时,就不能直接这样了,因为此时会有一个二义性的问题,即编译器会纠结传入的到底是哪个函数的地址。那这个时候怎么办呢?

就拿书上我画黄线的这个例如来说吧,Qt把QSpinBox的valueChanged这个信号重载了一次,也就是现在有两个同名的函数了,那我们可以定义两个函数指针啊,分别指向这两个函数,那么想连接哪个信号,就向connect中传入哪个信号对应的函数指针。这样就没有二义性的问题了,因为编译器知道了你传入的是哪个函数

a0d94e42560c892bae65b8158b1f8941.png

void (QSpinBox::*p1_valueChanged) (int) = &QSpinBox::valueChanged;

void (QSpinBox::*p2_valueChanged) (const QString &) = &QSpinBox::valueChanged;

和我们平时定义函数指针不同的地方在于:在这里定义一个指向类的成员函数的指针时,需要在前面指定一下这个函数指针它属于哪个类。

那么,就可以这样把信号与槽连接起来了:

connect(spinNum, p1_valueChanged, this, &widget::onValueChanged);

或者

connect(spinNum, p2_valueChanged, this, &widget::onValueChanged);

另外,这个槽函数也可以像信号一样重载,然后再分别定义对应的函数指针,再向connect中传递对应的函数指针。反正都同理啦。

所以当重载信号时,并非像这书上说的那样,不能用那种方法了,还是向connect中传信号函数地址,只是你要传一个指定好了的信号函数的地址,不然就会有二义性,程序会出错!

还有就是,我用那个SIGNAL和SLOT来整,信号与槽老是连接不上,也不报个错。。。

我只是觉得书上这一块没说好,自己也顺带写篇推文记一下,没有说这书不好的意思

b14ce9464d2c7742bdb65121e4202564.png,主要还是做一个学习笔记。

那么下面通过一个例子来试试,这里我重载的是一个自定义的信号。

fa1bcef72b4899fe53657a2217b56441.png

例子

(在QtCreater上编写的)

内容:做两个窗口,两个窗口上个一个按钮,点击哪个窗口上的按钮,就隐藏哪个窗口,然后显示另一个窗口。

思路:让一个窗口成为主窗口,在主窗口的类中实例化另一个窗口(子窗口)。在主窗口中点击按钮隐藏子窗口,这好办。但在子窗口中点击按钮隐藏主窗口,还是得折腾一下。可以在子窗口中点击按钮时,往外面发射一个信号,在主窗口的类中把这个信号与一个槽函数连接一下就行了。所以这就需要自定义一个信号了。

fa1bcef72b4899fe53657a2217b56441.png

上面讲的内容都在代码中加粗了,并以更大号的字体标出来了!

头文件

1. 声明主窗口类的头文件:widget.h

#ifndef WIDGET_H

#define WIDGET_H

#include 

#include 

#include "subwindow.h"

class Widget : public QWidget

{

Q_OBJECT

public:

explicit Widget(QWidget *parent = nullptr);

~Widget();

private:

//私有成员变量

QPushButton* btn;

SubWindow subW;

//私有成员函数

void setupUI();                     //初始化主窗口函数

void showSubWindow();               //

void btn1_sub();              //

void btn2_sub(int i, QString s);   //

};

#endif // WIDGET_H

2. 声明子窗口类的头文件:subwindow.h

#ifndef SUBWINDOW_H

#define SUBWINDOW_H

#include 

#include 

class SubWindow : public QWidget

{

Q_OBJECT

public:

explicit SubWindow(QWidget *parent = nullptr);

private:

//私有成员变量

QPushButton *btn1;

QPushButton *btn2;

//私有成员函数

void setupUI();       //初始化子窗口函数

void btn1_clicked();  //点击按钮1后要执行的那个槽函数(在槽函数中发射第一个重载信号)

void btn2_clicked();  //点击按钮1后要执行的那个槽函数(在槽函数中发射第一个重载信号)

signals:

//自定义信号,必须使用signals声明。这里重载了一个

void sig_showMainWindow();

void sig_showMainWindow(int, QString);

public slots:

//槽函数也就是一个函数,所以直接在成员函数那写就行,这里可以不写

};

#endif // SUBWINDOW_H

源文件

1. 定义主窗口类的头文件:widget.cpp

#include "widget.h"

#include 

//默认构造函数

Widget::Widget(QWidget *parent)

: QWidget(parent)

{

Widget::setupUI();  //在构造函数中调用初始化主窗口的函数

}

Widget::~Widget()

{

}

//定义初始化主窗口的函数

void Widget::setupUI()

{

//设置主窗口相关的参数

this->resize(400, 600);

this->move(500, 200);

this->setWindowTitle("Main Window");

//在主窗口中创建一个按钮,设置相关参数,连接信号与槽

btn = new QPushButton("隐藏主窗口,显示子窗口", this);

btn->resize(300, 50);

btn->move(50, 250);

connect(btn, &QPushButton::clicked, this, &Widget::showSubWindow);

//分别定义那两个指向自定义信号函数的指针

void (SubWindow::*p1_sig_hideMainWindow) () = &SubWindow::sig_showMainWindow;

void (SubWindow::*p2_sig_hideMainWindow) (int, QString) = &SubWindow::sig_showMainWindow;

//连接自定义信号和其对应的槽函数

connect(&this->subW, p1_sig_hideMainWindow,

this, &Widget::btn1_sub);

connect(&this->subW, p2_sig_hideMainWindow,

this, &Widget::btn2_sub);

}

//主窗口中那个按钮点击信号对应的槽函数

void Widget::showSubWindow()

{

this->hide();

this->subW.show();

}

//子窗口中点击第一个按钮发射出的信号所对应的槽函数(发射的第一个重载的信号)

void Widget::btn1_sub()

{

this->show();

this->subW.hide();

}

//子窗口中第二个按钮发射出的信号所对应的槽函数(发射的第二个重载的信号)

void Widget::btn2_sub(int i, QString s)

{

this->show();

this->subW.hide();

//打印一下发射出的信号所携带的信息

qDebug() <

}

2. 定义子窗口类的头文件:subwindow.cpp

#include "subwindow.h"

//默认构造函数

SubWindow::SubWindow(QWidget *parent) : QWidget(parent)

{

SubWindow::setupUI();  //在构造函数中调用初始化子窗口的函数

}

//定义初始化子窗口的函数

void SubWindow::setupUI()

{

//设置子窗口的相关参数

this->resize(400, 600);

this->move(900, 200);

this->setWindowTitle("Sub Window");

//创建一个按钮,点击它用于发射第一个重载的信号

btn1 = new QPushButton("Show sub window, Hide main window", this);

btn1->resize(300, 50);

btn1->move(50, 200);

btn1->setText("第一个重载信号");

//连接信号与槽

connect(btn1, &QPushButton::clicked, this, &SubWindow::btn1_clicked);

//创建一个按钮,点击它用于发射第二个重载的信号

btn2 = new QPushButton("Show sub window, Hide main window", this);

btn2->resize(300, 50);

btn2->move(50, 300);

btn2->setText("第二个重载信号");

//连接信号与槽

connect(btn2, &QPushButton::clicked, this, &SubWindow::btn2_clicked);

}

//第一个按钮的槽函数

void SubWindow::btn1_clicked()

{

emit this->sig_showMainWindow();

}

//第二个按钮的槽函数

void SubWindow::btn2_clicked()

{

emit this->sig_showMainWindow(1, this->btn2->text());

}

3. main函数:main.cpp

#include "widget.h"

#include 

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

QApplication a(argc, argv);

Widget w;

w.show();

return a.exec();

}

结果演示

cef66c4de09baa616279fd02742f39a9.gif

(不知道画质为啥这么差)

fa1bcef72b4899fe53657a2217b56441.png

[1] 王维波 栗宝鹃 侯春望. Qt5.9 C++ 开发指南[M].

赶在24点前发出去,为了明天把这个例子用matlab做一下,再发一篇推文。所以推文没多读几遍,可能不少地方表达的不通顺

d6f0f32199f9131affa08586bbd287ea.png

d6f0f32199f9131affa08586bbd287ea.png

d6f0f32199f9131affa08586bbd287ea.png

d6f0f32199f9131affa08586bbd287ea.png

d6f0f32199f9131affa08586bbd287ea.png

--END--

efcd69e07c4fa028435ea59f328e59c9.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值