所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。
槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。
槽能被用来接收信号者,除此之外它们也是普通的成员函数。槽不知道是否有信号与它连接起来,正如对象不知道它发出信号是否会被接收一样。这样的机制确保了可以使用Qt创建一个个完全独立的组件。你可以把你感兴趣的多个信号与一个个槽进行连接,也可以把一个信号与多个槽进行连接。甚至可以直接把一个信号连接到另一个信号(当第一个信号发送出去的时候,第二个信号紧接着被发送)。就这样,信号与插槽建立了强大的组件编程机制。
connect()函数最常用的一般形式:
connect(sender, signal, receiver, slot);
参数设置:
信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。
public slots:
void ASlot();
之后在mainwidget.cpp文件中定义槽函数:
void MainWidget::ASlot()
{
btn2->setText("^_^");
}
现在, 我们希望当Button2按下时, Button2显示的文本变成笑脸, 就需要将Button2的信号和我们自定义的槽函数连接:
connect(btn2, &QPushButton::clicked, this, &MainWidget::ASlot);
代码:
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include
#include
#include "subwidget.h"
class mainWidget : public QWidget
{
Q_OBJECT
private:
QPushButton btn1;
QPushButton *btn2;
public slots:
void Aslots();
public:
mainWidget(QWidget *parent = 0);
~mainWidget();
};
#endif // MAINWIDGET_H
mainwidget.cpp
#include "mainwidget.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
btn1.setParent(this);
btn1.setText("Close");
btn1.move(50,50);
btn2 = new QPushButton(this);
btn2->setText("btn_ok");
btn2->move(150,50);
connect(&btn1, &QPushButton::clicked, this, &MainWidget::close);
connect(btn2, &QPushButton::clicked, this, &MainWidget::ASlot);
}
void MainWidget::ASlot()
{
btn2->setText("^_^");
}
MainWidget::~MainWidget()
{
}
实现两个独立窗口之间的切换, 点击"Next" 跳到下一个窗口, 点击"Back" 返回到上一个窗口.
this->setWindowTitle("Window1"); // this->可以省略
this->resize(300, 200); // 长300, 宽200
之后修改Button2的文本"Button2"为"Next"
新建一个窗口
右键工程目录**“SignalAndSlot”** --> Add New:
选择 C++ --> C++ Class --> Choose:
输入Class name为SubWidget, Base class为QWidget, 点击Next, 点击Finish:
之后一个新的窗口类就新建好了:
修改新窗口的标题:
在subwidget.cpp中构造函数下, 设置窗口的标题为"Window2", 大小和Windows1一样:
this->setWindowTitle("Windows2");
this->resize(300, 200);
在新窗口中加入按键:
首先, 在subwidget.h中添加头文件, 然后声明按钮 b:
private:
QPushButton b;
在subwidget.cpp中, 对按钮进行编辑:
b.setParent(this);
b.setText("Back");
b.move(150, 50);
实例化SubWidget:
但是, 我们仅仅是写了一个新窗口的类, 还没有实例化, 所以我们在mainwidget.h中先包含subwidget的头文件, 然后实例化一个副窗口subWin对象:
SubWidget subWin;
建立信号与槽的连接:
接下来, 我们来实现点击"Next"显示Windows2功能, 其实就是b2点击这个信号, 触发副窗口的show(), 并隐藏主窗口.
将mainwidget.h和mainwidget.cpp中所有的mySlot改为nextSlot. (共三处)
我们修改mainwidget.cpp中nextSlot()的定义:
void MainWidget::nextSlot()
{
// 删除 b2->setText("^_^");
subWin.show();
this->hide();
}
connect(b2, &QPushButton::clicked, this, &MainWidget::nextSlot);
不变. 保存并运行, 就可以实现切换到Window2窗口了. 但是还没有返回主窗口功能.
信号的创建和发送:
要实现Back功能, 就需要在"Back"按钮按下后, 副窗口发送一个信号, 然后主窗口收到这个信号后, 显示自己, 隐藏副窗口, 逻辑如下:
Back按下的信号 ----> 副窗口发送信号
副窗口的信号 ----> 主窗口show, 副窗口hide
下面看代码怎么写:
在subwidget.h中声明一个自定义的信号, 和用于发送该信号的槽函数:
signals:
void backSignal();
public slots:
void sendSignal();
由于信号只需声明, 无需定义, 所以只要在subwidget.cpp定义槽函数来发送信号:
void SubWidget::sendSignal()
{
emit backSignal();
}
之后在Back按钮按下后, 通过这个槽函数发送返回信号:
connect(&b, &QPushButton::clicked, this, &SubWidget::sendSignal);
在mainwidget中需要再定义一个槽函数来处理back信号:
在mainwidget.h中声明槽函数
void backSlot();
之后在mainwidget.cpp中定义:
void MainWidget::backSlot()
{
this->show();
subWin.hide();
}
之后connect信号与槽, 收到副窗口发送的信号后返回主窗口:
connect(&subWin, &SubWidget::backSignal, this, &MainWidget::backSlot);
自己完成以下代码吧
完整代码:
链接: https://pan.baidu.com/s/1rtXU8e0oUy95mAok1zRDIA 密码: 7tc3
–来自百度网盘超级会员V5的分享