信号与槽是QT的一大创新,通过自定义信号与槽可以实现自己想实现的功能。
标准的信号与槽写法如下:
connect(&button,&QPushButton::clicked,this,&QWidget::close);
/*
* 对上面的connect信号与槽的说明
* &button :信号发出者,指针类型
* &QPushButton::clicked :处理的信号, &发送者的类名::信号名字 (不用加函数括号,只需要名字即可)
* this : 信号接收者 ,指针类型
* &QWidget::close :&接收者的类名::槽函数名字
*/
自定义槽,普通函数的用法
Qt5:任意的成员函数,普通全局函数,静态函数
槽函数需要和信号一致(参数,返回值)
由于信号都是没有返回值,所以槽函数一般都没有返回值
自定义信号:
信号必须有signals关键字来声明
信号没有返回值,但可以有参数
信号就是函数的声明,只需声明,无需定义
使用:emit (一般都是通过自定义槽函数发送信号出去)
简介:下面代码的梗概是在主窗口定义一个b2按钮,并定义信号与槽来打开子窗口s1,然后在子窗口s1中定义两个按钮sb1和sb2,sb1用来触发自定义的sb1sendSlot槽函数(这个槽函数用来发送sb1Signal()信号),sb2类似,来实现在子窗口中能进行信号广播,然后父类窗口对这个信号感兴趣,进而触发父类窗口的槽函数。(因为父类窗口能控制字类窗口,子类窗口不能反过来控制父类窗口(在子窗口中没有父类的指针),只能发送信号广播,让父类感兴趣)
贴上代码:
Headers文件:
①widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include "subwidget.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
subWidget s1; //头文件引入subwidget.h这个QWidget库,并实例化对象s1
~Widget();
private:
Ui::Widget *ui;
QPushButton *btn=new QPushButton;
QPushButton b2;
};
#endif // WIDGET_H
②subwidget.h
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include
#include
class subWidget : public QWidget
{
Q_OBJECT
public:
explicit subWidget(QWidget *parent = nullptr);
QPushButton sb1;
QPushButton sb2;
void sb1sendSlot();
void sb2sendSlot();
signals:
void sb1Signal();
void sb2Signal();
public slots:
};
#endif // SUBWIDGET_H
Sources文件:
①main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
②widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
btn->setParent(this); //btn在widget.h中是new出来的,是个指针,所以用函数得->
btn->setText("关闭主窗口");
btn->move(100,100);
this->resize(400,500); //this表示调用这个函数的对象,即widget这个主窗口
connect(btn,&QPushButton::clicked,this,&QWidget::close);
/*
* 对上面的connect信号与槽的说明
* btn :信号发出者,指针类型
* &QPushButton::clicked :处理的信号, &发送者的类名::信号名字
* this : 信号接收者 ,指针类型
* &QWidget::close :&接收者的类名::槽函数名字
*/
b2.setParent(this); //b2按钮是widget.h声明的按钮,这里指定父对象为this主窗口
b2.move(50,50);
b2.setText("打开新窗口");
connect(&b2,&QPushButton::released,&s1,&subWidget::show); //在主窗口按下b2按钮,次窗口s1就会show
//***以下两个conne是接收自定义的信号
/*
* sb1Signal是通过自定义槽函数sb1sendSlot发出的信号,
* 子窗口发出来就会广播,在下面这个this主窗口感兴趣就会调用槽函数
*/
connect(&s1,&subWidget::sb1Signal,this,&Widget::hide);
connect(&s1,&subWidget::sb2Signal,this,&Widget::show);
}
Widget::~Widget()
{
delete ui;
}
③subwidget.cpp
#include "subwidget.h"
subWidget::subWidget(QWidget *parent) : QWidget(parent)
{
//***sb1和sb2是在subWidget.h中声明的两个按钮
sb1.setParent(this);
sb1.move(50,50);
sb1.setText("关闭主窗口2");
connect(&sb1,&QPushButton::clicked,this,&subWidget::sb1sendSlot);
/*
* 对上面的connect函数声明
* &sb1 : 信号发出者,指针类型
* &QPushButton::clicked :处理的信号, &信号发出者的类型::信号名字
* this :信号接收者,指针类型
* &subWidget::sb1sendSlot :槽函数,信号处理函数 &接收者类名:槽函数名字
* 注意:这个槽函数名字是自定义的,在.h中的public下声明void函数,然后在.cpp下面定义。
*/
sb2.setParent(this);
sb2.move(20,20);
sb2.setText("显示主窗口");
connect(&sb2,&QPushButton::clicked,this,&subWidget::sb2sendSlot);
}
void subWidget::sb1sendSlot() //这个函数是自定义的槽函数,需要加类名作用域,在此定义
{
emit sb1Signal(); //在这个槽函数中发送这个信号,信号在.h的signal中声明,在前面加emit即发送
}
void subWidget::sb2sendSlot()
{
emit sb2Signal();
}
总结:感觉写代码可以debug,写的很清楚,而拖控件感觉不知道实现是怎么样的,后期修改也找不到对象,因此推荐写代码来做界面,便于后期维护,当然也可以先通过design拖控件先实现功能后,再写代码实现同样的功能。