自定义信号和槽
构建“顾客-服务员”点餐系统
学习了信号和槽机制之后,我们这节先来构建一个“顾客-服务员”点餐系统的一个小程序,首先回顾与下connect函数中的参数:(信号发出,信号,槽接收,槽函数)。
那么我们这个场景的信号发出者就是——顾客,信号就是——点餐,槽接收就是——服务员,槽函数就是——服务员询问顾客点什么。
- 接下来我们创建两个类:顾客custom,服务员waiter。
- 在custom.h中signal(信号)部分声明信号指令:void order(),在waiter.h中slot(槽)部分声明槽函数:void receive(); 注意:信号部分返回值为void,没有函数体;任何函数都能作为槽函数,而信号不能。
下面来看一下具体代码:
Custom.h
#ifndef CUSTOM_H
#define CUSTOM_H
#include <QWidget>
class Custom : public QWidget
{
Q_OBJECT
public:
explicit Custom(QWidget *parent = 0);
signals:
void order();
public slots:
};
#endif // CUSTOM_H
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Waiter.h
#ifndef WAITER_H
#define WAITER_H
#include <QWidget>
class Waiter : public QWidget
{
Q_OBJECT
public:
explicit Waiter(QWidget *parent = 0);
signals:
public slots:
void receive();
};
#endif // WAITER_H
Custom.cpp
#include "Custom.h"
Custom::Custom(QWidget *parent) : QWidget(parent)
{
}
Waiter.cpp
#include "Waiter.h"
#include<QDebug>
Waiter::Waiter(QWidget *parent) : QWidget(parent)
{
}
void Waiter::receive(){
qDebug()<<"您好,需要点什么?"<<endl;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "Custom.h"
#include "Waiter.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
Waiter wai;
Custom cus;
QObject::connect(&cus,&Custom::order,&wai,&Waiter::receive);
emit cus.order();
return a.exec();
}
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
实现功能:
这个简单的功能就实现了,那么看起来确实是优点呆哈,我们来改进一下:实现点击按钮->顾客点餐->服务员询问。
我们只需要将这个条件做一个转折:将问题分解成
- 按钮点击->顾客发出点餐动作
- 顾客发出点餐信号->服务员问点什么
这样我们只需要
- 在Custom.h的槽函数部分添加一个声明:void send();
- 在Custom.cpp中实现send()函数:emit order();
- 用connect()函数实现上述问题:
需要修改代码的文件为
Custom.h
#ifndef CUSTOM_H
#define CUSTOM_H
#include <QWidget>
class Custom : public QWidget
{
Q_OBJECT
public:
explicit Custom(QWidget *parent = 0);
signals:
void order();
public slots:
void send();
};
#endif // CUSTOM_H
Custom.cpp
#include "Custom.h"
Custom::Custom(QWidget *parent) : QWidget(parent)
{
}
void Custom::send(){
emit order();
}
Main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include "Custom.h"
#include "Waiter.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
Waiter wai;
Custom cus;
QPushButton but(&w);
but.show();
QObject::connect(&but,&QPushButton::clicked,&cus,&Custom::send);// 点击按钮——顾客发出指令——点什么
QObject::connect(&cus,&Custom::order,&wai,&Waiter::receive);
return a.exec();
}
最终实现:
点击按钮:
lambda表达式与槽
同样的,我么也可以用之前学过的lambda表达式参与connect()函数的构建:
QApplication a(argc, argv);
MainWindow w;
w.show();
waiter wai;
custom cus;
void (custom::*p)() = custom::order;
void (custom::*p1)(QString) = custom::order;
QObject::connect(&cus,p1,&wai,[](QString str){//lambda表达式
qDebug()<<str;
});
emit cus.order("点啥");
图中的知识点:
- 信号函数的参数数量要大于等于槽函数参数数量,如果等于槽函数参数数量,参数类型要相同
- 因为lambda表达式是一个函数指针,所以可视为槽函数