一 信号与槽函数
#include "mainwindow.h"
#include <QPushButton>
#include <iostream>
using namespace std;
//我们的目的是在 window中加入一个button,当点击这个button后,关闭 MainWindow 。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//注意,这里是new 了一个 QpushButton的,那么理论上要 delete 这个loginButton 。这里为什么 没有呢?
QPushButton * loginButton = new QPushButton();
loginButton->setText("登陆");
loginButton->setParent(this); // 将自己挂载到当前的 mianwindow上,这意味着,当 mainwindows 销毁的时候,loginbutton 会跟着销毁,因此不用手动的调用 elete loginbutton
loginButton->setFixedSize(100,30); // 设置button 为固定大小
//我们将 loginbutton 的 clicked信号,给MainWindow 的 close槽函数。
//qpushbutton 的clicked 信号,是qpushbutton 自带的信号
//mainwindows 的close 槽函数,是 mainwindows 自带的槽函数
connect(loginButton,&QPushButton::clicked,this,&MainWindow::close);
}
MainWindow::~MainWindow()
{
}
二 自定义信号和 自定义 槽函数
1.自定义信号,添加一个C++ 类,要继承 QObject
主要你要自定义信号与槽,就一定要 Add Q_OBJECT
sender.h 文件
#ifndef SENDER_H
#define SENDER_H
#include <QObject>
class Sender : public QObject
{
//主要你要自定义信号与槽,就一定要 Add Q_OBJECT,这个取消了会有问题
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr);
signals:
//自定义信号,只需要在.h文件中声明就可以了,不需要在.cpp中实现
void exit();
void start();
};
#endif // SENDER_H
2.自定义槽函,添加一个C++类,要继承 QObject
在receiver.h 中定义这两个槽函数
在receiver.cpp中实现这两个槽函数
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
class receiver : public QObject
{
//主要你要自定义信号与槽,就一定要 Add Q_OBJECT,这个取消了会有问题
Q_OBJECT
public:
explicit receiver(QObject *parent = nullptr);
signals:
//槽函数是要给别人调用的,因此在public slots 后 写 槽函数,在.cpp文件中写实现.
public slots:
void handleExit();
void handleStart();
};
#endif // RECEIVER_H
#include "receiver.h"
#include <iostream>
using namespace std;
receiver::receiver(QObject *parent) : QObject(parent)
{
}
void receiver::handleExit(){
cout<<"receiver handleExit method "<<endl;
}
void receiver::handleStart(){
cout<<"receiver handleStart method "<<endl;
}
3.调用
这里为了方便期间,将上述两个类 重命名为 customerreceiver.h 和 customersender.h
//将信号发送者 和 信号 接受者 建立关联
//使用emit 发送信号, 实际上就是 调用 发送者的信号函数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "customersender.h"
#include "customerreceiver.h"
#include <iostream>
using namespace std;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
cout<<"qt custom single custom slot"<<endl;
ui->setupUi(this);
CustomerSender * customersender = new CustomerSender;
CustomerReceiver * customerrecevier = new CustomerReceiver();
//将信号发送者 和 信号 接受者 建立关联
connect(customersender,&CustomerSender::start,
customerrecevier,&CustomerReceiver::handleStart);
connect(customersender,&CustomerSender::exit,
customerrecevier,&CustomerReceiver::handleExit);
cout<<"00000 log for watch"<<endl;
//使用emit 发送信号, 实际上就是 调用 发送者的信号函数
emit customersender->start();
cout<<"11111log for watch"<<endl;
emit customersender->exit();
cout<<"222"<<endl;
//由于 customersender 和 customerrecevier 并没有挂载到当前mainwindows上,类似这样customersender->setParent(this);因此要手动delete
delete customersender;
delete customerrecevier;
}
MainWindow::~MainWindow()
{
delete ui;
}
4. 当自定义信号 和 自定义槽函数 有参数或者返回值的时候
自定义信号 addmethodstart ,参数为 int a 和 int b
返回值double 目前不知道有啥用
signals:
//自定义信号,只需要在.h文件中声明就可以了,不需要在.cpp中实现
void exit();
void start();
double addmethodstart(int a ,int b );
自定义槽函数
int handleAddFuncation();
double handleAddFuncation2(int n , int m);
int CustomerReceiver::handleAddFuncation(){
cout<<"CustomerReceiver handleAddFuncation method return 100"<<endl;
return 100;
}
double CustomerReceiver::handleAddFuncation2(int n , int m){
cout<<"CustomerReceiver handleAddFuncation2 method return n+m "<< n+m << endl;
return n+m;
}
当我们发送一个信号的时候,如果有槽函数有对应的 int,int 参数,则会接受 信号发送的2000,3000的值传递到槽函数中。
如果槽函数没有对应的int,int 参数,则不传递
connect(customersender,&CustomerSender::addmethodstart,
customerrecevier,&CustomerReceiver::handleAddFuncation);
cout<< emit customersender->addmethodstart(200,300);//由于 handleAddFuncation 函数没有参数,因此这个200,300传递不到槽函数handleAddFuncation中
cout<<"333"<<endl;
connect(customersender,&CustomerSender::addmethodstart,
customerrecevier,&CustomerReceiver::handleAddFuncation2);
cout<< emit customersender->addmethodstart(2000,3000);//由于handleAddFuncation2 有int,int 的参数 ,因此这个2000,3000会传递给槽函数 handleAddFuncation2
返回值问题,信号的返回值目前没有发现意义是啥,
槽函数的返回值 可以通过 emit 信号函数返回。
例如:
cout<< emit customersender->addmethodstart(200,300);
会打印 100出来,这是因为 对应的槽函数 handleAddFuncation 返回值是100
5. 连接多个信号
connect 函数除了可以连接一个 信号和一个槽函数外,
还可以连接一个信号 和 另一个信号 .
类似于连锁反应
customersender2.h
#ifndef CUSTOMERSENDER2_H
#define CUSTOMERSENDER2_H
#include <QObject>
class customersender2 : public QObject
{
Q_OBJECT
public:
explicit customersender2(QObject *parent = nullptr);
signals:
void deletebutton2();
};
#endif // CUSTOMERSENDER2_H
customersender3.h
#ifndef CUSTOMERSENDER3_H
#define CUSTOMERSENDER3_H
#include <QObject>
class customersender3 : public QObject
{
Q_OBJECT
public:
explicit customersender3(QObject *parent = nullptr);
signals:
void deletebutton3();
};
#endif // CUSTOMERSENDER3_H
customerreceuver2.h
#ifndef CUSTOMERRECEUVER2_H
#define CUSTOMERRECEUVER2_H
#include <QObject>
class customerreceuver2 : public QObject
{
Q_OBJECT
public:
explicit customerreceuver2(QObject *parent = nullptr);
signals:
public slots:
void handledeletebutton2();
};
#endif // CUSTOMERRECEUVER2_H
customerreceuver3.h
#ifndef CUSTOMERRECEUVER3_H
#define CUSTOMERRECEUVER3_H
#include <QObject>
class customerreceuver3 : public QObject
{
Q_OBJECT
public:
explicit customerreceuver3(QObject *parent = nullptr);
signals:
public slots:
void handledeletebutton3();
};
#endif // CUSTOMERRECEUVER3_H
customerreceuver2.cpp
#include "customerreceuver2.h"
#include <iostream>
using namespace std;
customerreceuver2::customerreceuver2(QObject *parent) : QObject(parent)
{
}
void customerreceuver2::handledeletebutton2(){
cout<<"customerreceuver2::handledeletebutton2"<<endl;
}
customerreceuver3.cpp
#include "customerreceuver3.h"
#include <iostream>
using namespace std;
customerreceuver3::customerreceuver3(QObject *parent) : QObject(parent)
{
}
void customerreceuver3::handledeletebutton3(){
cout<<"customerreceuver3::handledeletebutton3"<<endl;
}
调用
cout<<" single to single"<<endl;
customersender2 *cus2 = new customersender2;
customersender3 *cus3 = new customersender3;
customerreceuver2 *cusre2 = new customerreceuver2;
customerreceuver3 *cusre3 = new customerreceuver3;
connect(cus2, &customersender2::deletebutton2,
cusre2,&customerreceuver2::handledeletebutton2);
emit cus2->deletebutton2();
cout<<"111"<<endl;
connect(cus3, &customersender3::deletebutton3,
cusre3,&customerreceuver3::handledeletebutton3);
emit cus3->deletebutton3();
cout<<"222 "<<endl;
cout<<"after this line will be test single to single"<<endl;
//让 sender2 的信号deletebutton2 唤醒 sender3 的信号 deletebutton3
connect(cus2, &customersender2::deletebutton2,
cus3, &customersender3::deletebutton3);
emit cus2->deletebutton2();
cout<<"333333"<<endl;
// single to single
// customerreceuver2::handledeletebutton2
// 111
// customerreceuver3::handledeletebutton3
// 222
// after this line will be test single to single
// customerreceuver2::handledeletebutton2
// customerreceuver3::handledeletebutton3
// 333333
6.labmda 表达式
//for test labmda,假设我们不想写receiver
connect(cus2, &customersender2::deletebutton2,[](){
cout<<"labmda called"<<endl;
});
emit cus2->deletebutton2();
cout<<"666666"<<endl;
三 当QT使用 genetate form 创建UI后,如何使用 信号和槽函数呢?
也就是说,我们使用了QT 的 generate form 来创建UI
我们在弄了两个pushbutton,一个登陆,一个注册,可以观察到 QT会给key 命名为 pushButton,一个为pushButton_2,当然可以改动这个key的值,
我们这里重新命名为 loginbutton和registerbutton
检查 编辑 下的 UI 的button,如下:
那么我们想要给这两个button 添加 信号和槽事件应该怎么弄呢?
点击 "转到槽" 做了两件事情
1. 点击那个信号 相当于 选择了那个 信号
2.然后生成 该信号 对应的 槽函数
例如我们点击了 clicked() 信号,就会生成 void on_loginbutton_clicked() 参函数
槽函数的位置
那么 emit 是在什么时候调用呢?实际上我们是看不到的,QT内部帮我们实现了,只要我们完成了上述的 button 的 转到槽函数, 就可以了
测试:
手动的写 槽函数,而不是通过自动生成