subwidget.h
#ifndef SUBQWIDGET_H
#define SUBQWIDGET_H
#include <QWidget>
#include<QPushButton>
class SubQWidget : public QWidget
{
Q_OBJECT
public:
explicit SubQWidget(QWidget *parent = nullptr);
void SendSlot(); //发射信号的槽
signals:
/*信号必须有signals关键字来声明
* 信号没有返回值,但可以有参数
* 信号就是函数的声明,只需声明,无需定义
* 使用: emit mySignal();
*/
void mySignal(); //小弟窗口自定义信号
private:
QPushButton b;
};
#endif // SUBQWIDGET_H
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include<QPushButton>
#include"subqwidget.h"
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
void MySlot(); //改变b2的内容
void exchang_Slot();//切换窗口
void pro(); //老大窗口处理小弟窗口发来的信号
private:
QPushButton b1;
QPushButton* b2; //按钮指针,用来指定父类对象
QPushButton b3;
SubQWidget w;//小弟窗口对象
};
#endif // MAINWIDGET_H
subwidget.cpp
#include "subqwidget.h"
SubQWidget::SubQWidget(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("小弟");
b.setParent(this);
b.setText("切换到父窗口");
connect(&b,&QPushButton::pressed,this,&SubQWidget::SendSlot); //当按钮按下时,发送信号给老大
resize(300,300); //设置大小
}
void SubQWidget::SendSlot()
{
emit mySignal(); //发射信号
}
mainwidget.cpp
#include "mainwidget.h"
#include<QPushButton>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
//1.通过setparent指定父类对象
b1.setParent(this);
b1.setText("close");
b1.move(100,100); //移动位置
//2.通过构造函数指定父类对象MainWdigets,当前对象是MainWidgets
b2 = new QPushButton(this);//当前MainWidget对象this
b2->setText("button");
b2->move(200,200);
//信号和槽关联
connect(&b1,&QPushButton::clicked,this,&MainWidget::close);
/*自定义槽:普通函数的用法
* QT5:任意的成员函数,普通全局函数,静态函数
* 槽函数需要和信号一致(参数,返回值)
* 由于信号都是没有返回值,所以槽函数也没有返回值
* 一个信号可以关联多个槽(relasead关联Myslot和hide两个槽,
* released分别代表按钮的按下和抬起
*/
connect(b2,&QPushButton::released,this,&MainWidget::MySlot);//按钮b2按下时内容改为123
connect(b2,&QPushButton::released,&b1, &QPushButton::hide);//按钮b2抬起时把b1隐藏
//信号:短信
//槽:接收短信的手机
setWindowTitle("老大");
b3.setText("切换到子窗口");
b3.setParent(this);
b3.move(50,50);
//w.show(); //此处就是实现窗口独立
//按钮按下切换到子窗口的关联
connect(&b3,&QPushButton::released,this,&MainWidget::exchang_Slot);//注意:此处槽函数只能使用类名::进行访问,不能通过对象,否则报错
connect(&w, &SubQWidget::mySignal, this, &MainWidget::pro);
resize(300,300);//设置窗口大小
QPushButton * b4 = new QPushButton(this);
b4->setText("Lambda表达式");
b4->move(150,150);
int a = 10, b = 100;
/*lambda表达式,匿名函数对象,c++11新特性,项目文件CONFIG += C++11
[](){}组成,[]代表表达式所接受的范围,以值传递方式进行传递[a,b]代表函数体只能使用ab,不能使用其他变量
[]里面通常用=,表示允许传入外部变量,而且这样安全。当然也可以使用 & 或 this以引用的方式传入,this表示将本类的成员传入,
但是不建议用&,因为会出现内存不完全释放问题。
重点:信号的参数必须和lambda表达式中()里的参数一致。
还有,外部的变量允许被修改,只需在()加上mutable 。示例如下:
*/
/* connect(b4,&QPushButton::released,this,
[a,b]() mutable
{
qDebug()<<"11111"<<endl;
a = 11;
qDebug()<<a<<b<<endl;
}
);*/
connect(b4,&QPushButton::released,this,
[=]() mutable
{
qDebug()<<"11111"<<endl;
b4->setText("lambda");
a = 11;
qDebug()<<a<<b<<endl;
}
);
}
void MainWidget::MySlot(){
b2->setText("123");
}
void MainWidget::exchang_Slot(){
//子窗口显示
w.show();
//本窗口隐藏
this->hide();
}
void MainWidget::pro()
{
//子窗口隐藏
w.hide();
//本窗口显示
this->show();
}
MainWidget::~MainWidget()
{
}
main.cpp
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;//执行MainWidget的构造函数
w.show();
return a.exec();//停在这人
}
当触发Lambda表达式按钮时,应用程序会输出a,b的值。
注意:
在进行窗口切换的时候,父类切换子类窗口直接按钮按下进行关联就可以直接切换(槽函数将自己隐藏,子类显示)connect(&b3,&QPushButton::released,this,&MainWidget::exchang_Slot);,
而子类切父类的时候却不能这样,因为父类中有子类的对象w而子类却没有父类对象,除了自定义槽之外,还需要自定义信号发射给父类,让父类自己对信号进行处理,就像老板和员工的关系,老板可以命令员工,员工不能命令老板一样
2.指定父类窗口的两个方法: 使用setparent(),或者使用构造函数传参。
3.在创建子类窗口对象时,不能在基类构造函数里面创建,因为是局部的,构造函数执行完毕就没有了。
为什么要指定父类对象?有什么好处
答:为了使子类窗口在父类窗口里面。指定父类有两种方式 使用setparent(),或者使用构造函数传参。
好处就是使得子类窗口不用每个都使用show单独显示,只需要对父类窗口使用show就可以把子类父类的窗口显示出来。很方便。
怎样创建子类窗口