发帖那个网站好 做装修的,thinkcmf和wordpress,北京漫步云端网站建设,惠州网络推广平台一、信号和槽机制 所谓信号槽#xff0c;实际就是观察者模式。当某个事件发生之后#xff0c;比如#xff0c;按钮检测到自己被点击了一下#xff0c;它就会发出一个信号#xff08;signal#xff09;。这种发出是没有目的的#xff0c;类似广播。如果有对象对这个信号…一、信号和槽机制 所谓信号槽实际就是观察者模式。当某个事件发生之后比如按钮检测到自己被点击了一下它就会发出一个信号signal。这种发出是没有目的的类似广播。如果有对象对这个信号感兴趣它就会使用连接connect函数意思是将想要处理的信号和自己的一个函数称为槽slot绑定来处理这个信号。也就是说当信号发出时被连接的槽函数会自动被回调。 连接函数connect 参数 参数1信号的发送者 参数2发送的信号(函数地址) 参数3信号的接收者 参数4处理的槽函数(函数的地址) 优点松散耦合 实现点击按钮关闭窗口的案例 connect(myBtn,MyPushButton::clicked,this,myWidget::close);
//connect(myBtn,QPushButton::clicked,this,QPushButton::close);使用父类 二、自定义信号和槽 自定义信号 写到signals 下 返回void 需要声明不需要实现 可以有参数可以重载 自定义槽函数 返回void 需要声明也需要实现 可以有参数可以重载 写到public slot下或者public或者全局函数 触发自定义的信号 emit自定义信号 案例下课后老师触发饿了信号学生响应信号请客吃饭
student.h
#ifndef STUDENT_H
#define STUDENT_H#include QObjectclass Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent nullptr);//返回值void需要声明也需要实现//可以有参数可以发生重载void treat();signals:};#endif // STUDENT_Hstudent.cpp
#include student.h
#includeQDebugStudent::Student(QObject *parent) : QObject(parent)
{}void Student::treat()
{qDebug()请老师吃饭;
}teacher.h
#ifndef TEACHER_H
#define TEACHER_H#include QObjectclass Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent nullptr);signals://自定义信号 写到signals下//返回值使void只需要声明不需要实现//可以有参数可以重载void hungry();};#endif // TEACHER_Hteacher.cpp
#include teacher.hTeacher::Teacher(QObject *parent) : QObject(parent)
{}widget.h
#ifndef WIDGET_H
#define WIDGET_H#include QWidget
#includeteacher.h
#includestudent.h
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:Ui::Widget *ui;Teacher *zt;Student *st;void ClassIsOver();
};
#endif // WIDGET_Hwidget.cpp
#include widget.h
#include ui_widget.h//Teacher类 老师类
//Student类 学生类
//下课后老师触发一个信号饿了学生响应信号请客吃饭
Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);//创建一个老师对象this-zt new Teacher(this);//创建一个学生对象this-st new Student(this);//老师饿了 学生请客的连接connect(zt,Teacher::hungry,st,Student::treat);//调用下课函数ClassIsOver();
}void Widget::ClassIsOver()
{//下课函数调用后触发老师饿了的信号emit zt-hungry();
}Widget::~Widget()
{delete ui;
}
三、自定义信号和槽发生重载的解决办法 需要利用函数指针明确指向函数的地址 void(Teacher:: *teacherSignal)(QString foodName) Teacher::hungry;
void(Student:: *studentSlot)(QString foodName) Student::treat; QString转成char* .toUtf8()先转为AByteArray .date再转为char* student.h
#ifndef STUDENT_H
#define STUDENT_H#include QObjectclass Student : public QObject
{Q_OBJECT
public:explicit Student(QObject *parent nullptr);//返回值void需要声明也需要实现//可以有参数可以发生重载void treat();void treat(QString foodName);//重载版本声明signals:};#endif // STUDENT_Hstudent.cpp
#include student.h
#includeQDebugStudent::Student(QObject *parent) : QObject(parent)
{}void Student::treat()
{qDebug()请老师吃饭;
}void Student::treat(QString foodName)//重载版本实现
{//QString-char * 先转成QByteArray(.toUtf8())再转char *(.data)qDebug()请老师吃饭老师要吃:foodName.toUtf8().data();
}teacher.h
#ifndef TEACHER_H
#define TEACHER_H#include QObjectclass Teacher : public QObject
{Q_OBJECT
public:explicit Teacher(QObject *parent nullptr);signals://自定义信号 写到signals下//返回值使void只需要声明不需要实现//可以有参数可以重载void hungry();void hungry(QString);//重载版本};#endif // TEACHER_Hteacher.cpp
#include teacher.hTeacher::Teacher(QObject *parent) : QObject(parent)
{}widget.h
#ifndef WIDGET_H
#define WIDGET_H#include QWidget
#includeteacher.h
#includestudent.h
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:Ui::Widget *ui;Teacher *zt;Student *st;void ClassIsOver();
};
#endif // WIDGET_Hwidget.cpp
#include widget.h
#include ui_widget.h//Teacher类 老师类
//Student类 学生类
//下课后老师触发一个信号饿了学生响应信号请客吃饭
Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);//创建一个老师对象this-zt new Teacher(this);//创建一个学生对象this-st new Student(this);// //老师饿了 学生请客的连接
// connect(zt,Teacher::hungry,st,Student::treat);// //调用下课函数
// ClassIsOver();//连接带参数的信号和槽//指针-地址//函数指针-函数地址void(Teacher:: *teacherSignal)(QString foodName) Teacher::hungry;void(Student:: *studentSlot)(QString foodName) Student::treat;connect(zt,teacherSignal,st,studentSlot);ClassIsOver();}void Widget::ClassIsOver()
{//下课函数调用后触发老师饿了的信号//emit zt-hungry();emit zt-hungry(宫保鸡丁);//重载版本
}Widget::~Widget()
{delete ui;
} 说明 connect(zt,Teacher::hungry,st,Student::treat); 若使用老师饿了的地址Teacher::hungry和学生请客的地址Student::treat则不能区分是否带参故出错(带参和不带参地址一样) 解决方案 对于函数地址Teacher::hungry我们使用函数指针指向函数地址 函数指针定义方式函数返回值类型(*指针变量名)(函数参数列表)如下 void( *teacherSignal)(QString foodName) Teacher::hungry 在声明成员函数的函数地址的时候要把成员函数的作用域放在指针前面正确写法如下 void(Teacher:: *teacherSignal)(QString foodName) Teacher::hungry 四、信号连接信号 #include widget.h
#include ui_widget.h
#includeQPushButton//Teacher类 老师类
//Student类 学生类
//下课后老师触发一个信号饿了学生响应信号请客吃饭
Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{ui-setupUi(this);//创建一个老师对象this-zt new Teacher(this);//创建一个学生对象this-st new Student(this);// //老师饿了 学生请客的连接
// connect(zt,Teacher::hungry,st,Student::treat);// //调用下课函数
// ClassIsOver();//连接带参数的信号和槽//指针-地址//函数指针-函数地址void(Teacher:: *teacherSignal)(QString foodName) Teacher::hungry;void(Student:: *studentSlot)(QString foodName) Student::treat;connect(zt,teacherSignal,st,studentSlot);// ClassIsOver();//点击一个下课的按钮再触发下课QPushButton *btn new QPushButton(下课,this);//重置窗口大小btn-resize(100,40);//点击按钮 触发下课//connect(btn,QPushButton::clicked,this,Widget::ClassIsOver);//无参信号和槽连接void(Teacher:: *teacherSignal2)(void) Teacher::hungry;void(Student:: *studentSlot2)(void) Student::treat;connect(zt,teacherSignal2,st,studentSlot2);//信号和信号连接connect(btn,QPushButton::clicked,zt,teacherSignal2);//断开信号//disconnect(zt,teacherSignal2,st,studentSlot2);}void Widget::ClassIsOver()
{//下课函数调用后触发老师饿了的信号//emit zt-hungry();emit zt-hungry(宫保鸡丁);
}Widget::~Widget()
{delete ui;
} 运行点击按钮下课则输出但窗口不会关闭。断开信号不注释点击按钮则不输出 拓展 1.信号可以连接信号 2.信号可以连接多个槽函数(点击按钮先输出再关闭窗口[连接close即可]) 3.多个信号可以连接一个槽函数 4.信号和槽函数的参数必须―—对应 5.信号的参数个数可以多于槽的参数的个数 五、lambda表达式 Lambda表达式用于定义并创建匿名的函数对象 []标识符 匿名函数 值传递 引用传递参数 ()参数 {}实现体 mutatle修饰值传递变量可以修改拷贝出的数据改变不了本体 返回值()[] -init {} labmda表达式最常用 [](){} //利用lambda表达式实现点击按钮关闭窗口QPushButton *btn2 new QPushButton;btn2-setText(关闭);btn2-move(100,0);btn2-setParent(this);connect(btn2,QPushButton::clicked,this,[](){this-close();emit zt-hungry(宫保鸡丁);});
运行点击下课输出请老师吃饭点击关闭输出请老师吃饭老师要吃: 宫保鸡丁同时关闭窗口
输出如下所示 作业
两个按钮实现
#include widget.h
#include ui_widget.h
#includeQPushButton
#includeQWidgetWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);QPushButton *open_btn new QPushButton(open,this);open_btn-resize(80,30);QPushButton *close_btn new QPushButton(close,this);close_btn-resize(80,30);close_btn-move(0,100);QWidget *window new QWidget;window-setWindowTitle(other_window);setWindowTitle(work_window);connect(open_btn,QPushButton::clicked,window,[](){window-show();});connect(close_btn,QPushButton::clicked,window,[](){window-close();});}Widget::~Widget()
{delete ui;
}
一个按钮实现
#include widget.h
#include ui_widget.h
#includeQPushButton
#includeQWidgetWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);QPushButton *btn new QPushButton(open,this);setWindowTitle(work_window);QWidget *window new QWidget;window-setWindowTitle(other_window);connect(btn,QPushButton::clicked,window,[](){if(btn-text()open){btn-setText(close);window-show();}else if(btn-text()close){btn-setText(open);window-close();}});}Widget::~Widget()
{delete ui;
}