20200528
有3个窗体,怎么实现3个窗体之间的切换?(信号和槽)
思路:(1)分别有1,2,3号窗体
(2)1号窗体中,加上2号头文件,并且实例化2号的空间
(3)在1号窗体中,绑定2号窗体发送过来的信号,并用槽去处理(显示1号窗体)
(4)在1号窗体按钮上 show 2号窗体
创建第1个界面:PushButton*1、Label*2
创建第2个界面:PushButton*2、Label*2
把第二个页面的头文件引入第一个页面的头文件中:
【代码篇】
(有this)子窗体也在父窗体中显示
(不要this)并列窗体,分别显示。
(对象形式用全局变量;指针形式用局部变量)
//第一种方式:会出现多个第2页面(局部变量压根就不行,局部指针多窗口)
//第二三种方式:只出现1个第2页面(全局变量,全局指针)
全局变量:只创建一个窗体,永远只有1个。
指针局部变量:创建多个窗体,因为点击1次,new1个对象,再点击1次,再new了1个对象。
SecForm *tf1 = new SecForm();//指针形式
指针全局变量:很奈斯的方式啊,完美!
第一个页面GO>>第二个页面成功实现,代码如下:(firstform.cpp)
#include "firstform.h"
#include "ui_firstform.h"
#include <QMovie>
FirstForm::FirstForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::FirstForm)
{
ui->setupUi(this);
Init();//调用
//绑定:处理1号窗体单击事件
connect(ui->pushButton,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickGoSecForm(bool)));
}
FirstForm::~FirstForm()
{
delete ui;
}
【Function】
void FirstForm::Init(){
//动画显示
QMovie *movie = new QMovie("../0528Form2Form/Big.gif");//加载文件:注意目录的斜杠方向(是/)(不是\)//..表示当前文件的上级目录。完整目录E:/QtCode/0528Form2Form/Big.gif
movie->start();//动起来
ui->label->setMovie(movie);//固定位置
ui->label->setScaledContents(true);//缩放内容
//处理单击事件:跳转到第二页面
connect(ui->pushButton,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickGoSecForm(bool)));
pot2 = new SecForm();//空间分配。注意:千万不要用this指针,否则会在父窗体中显示
}
【Slots】
void FirstForm::doProcessClickGoSecForm(bool){
//创建第2个窗体,记得在头文件中引入第2个页面的头文件
//(对象形式用全局变量;指针形式用局部变量或全局变量的比较)
//【1】第一种方式:指针形式(局部),会出现多个第2页面(因为每次都new,会创建多个窗体)
// SecForm *tf1 = new SecForm(this);//指针形式(有this,子窗体将在父窗体中直接显示)
// tf1->show();
// SecForm *tf1 = new SecForm();//指针形式:出现多个第2页面(无this,是并列窗体)
// tf1->show();//指针形式:每次都new,会创建多个窗体 (new的意思就是“创建”)
//【2】第二种方式:t1全局变量————只创建1个窗体(与局部变量做对比)
// SecForm t1;//仿照main.cpp,t1是局部变量
// t1.show();//这种方式行不通,因为资源是局部的,一开始就释放掉了。在该函数内部执行完,就没了。
// //头文件中定义全局变量 SecForm t1;//全局变量
// t1.show();//全局变量t1,只创建1个窗体
//【3】第三种方式:把指针定义为全局的(只new一个对象)————一开始就分配好空间 pot2 = new SecForm();
pot2->show(); // 头文件中定义全局指针 SecForm *pot2;
this->hide();//隐藏当前页面,显示第2页面
}
—————————————————分割线———————————————————
继续:第二页面的功能实现( Back 和 Next )
【返回上一页Back1】发射信号给第1个窗体,让它显示出来。
先绑定
connect(ui->Back1,SIGNAL(clicked(bool)),this,SLOT(doProcessClickBack1()));
然后窗体2发信号,窗体1收信号
emit SignalShowFirstForm(QString::number(clickCount));
实现代码如下:(secform.cpp) 窗体2发信号
#include "secform.h"
#include "ui_secform.h"
#include <QMovie>
SecForm::SecForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecForm)
{
ui->setupUi(this);
Init();
}
SecForm::~SecForm()
{
delete ui;
}
/【Function】/
void SecForm::Init(){
clickCount = 0;//清空(按钮点击次数)
//动画显示
QMovie *movie = new QMovie("../0528Form2Form/jump.gif");//加载文件:注意目录的斜杠方向(是/)(不是\)//..表示当前文件的上级目录。完整目录E:/QtCode/0528Form2Form/Big.gif
movie->start();//动起来
ui->label->setMovie(movie);//固定位置
ui->label->setScaledContents(true);//缩放内容
//绑定
connect(ui->Back1,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickBack1(bool)));
}
/【Slots】/
void SecForm::doProcessClickBack1(bool){
clickCount++; //每点击一次,就++
//窗体2发射信号,通知第1个窗体显示。统计点击了多少次(发射了多少次信号) //窗体1接收信号
emit SignalShowFirstForm(QString::number(clickCount)); //number:把int转换为QString类型
this->hide();//发射信号被处理后,第2窗体把自己隐藏
}
(firstform.cpp) 窗体1收信号
—————————————————分割线———————————————————
继续实现:【下一页】
创建新窗体ThdForm: LCD设置ui属性digitCount为2(显示两位)
QTimer对LCD的设置,代码如下:
(1)头文件中添加(thdform.h)
#include <QTimer>
private slots:
void doProcessTimeOut();//超时信号处理
private:
Ui::ThdForm *ui;
int count;//全局计时
QTimer *myTimer;
void Init();//初始化对象
(2)源文件中(thdform.cpp)
#include "thdform.h"
#include "ui_thdform.h"
ThdForm::ThdForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ThdForm)
{
ui->setupUi(this);
Init();//调用初始化对象的函数
}
ThdForm::~ThdForm()
{
delete ui;
}
/【Function】/
void ThdForm::Init(){
count = 0;
//LCD
myTimer = new QTimer(this);//分配空间,对象释放this
connect(myTimer,SIGNAL(timeout()),
this,SLOT(doProcessTimeOut()));
myTimer->start(100);//让时间跑起来:100ms一次
}
/【Slots】/
void ThdForm::doProcessTimeOut(){
count++;
if(count == 100)
count =0;
ui->lcdNumber->display(count);
}
(3)头文件中(secform.h)
第3个窗体的头文件添加到第2个窗体
用指针形式初始化第3个窗体对象的指针
ThdForm *pot3;
槽函数:
private slots:
void doProcessGoThdForm(bool);
(4)源文件中(secform.cpp)
分配空间,绑定
—————————————————分割线———————————————————
继续实现:【返回第二页】
不能再new第2个窗体,因为第2个窗体的资源还在,只是隐藏起来了
如果在这里再创建第2个窗体,这就叫做内存泄漏
所以我们在第3个窗体中给第2个窗体发送通知:让其显示
void ThdForm::doProcessBack2(){
//第3窗体给第2窗体发送信号,通知2号窗体显示————第2窗体接收信号
emit SignalShowSecForm();
this->hide();
}
第2个窗体接收信号,并处理
connect(pot3,SIGNAL(SignalShowSecForm()),
this,SLOT(doProcessShow()));
void SecForm::doProcessShow(){
this->show();//【返回第二页面】显示
}
至此,大功告成!!!!!!
3个头文件代码如下:(*.h)
#ifndef FIRSTFORM_H
#define FIRSTFORM_H
#include <QWidget>
#include "secform.h"
namespace Ui {
class FirstForm;
}
class FirstForm : public QWidget
{
Q_OBJECT
public:
explicit FirstForm(QWidget *parent = 0);
~FirstForm();
private slots:
void doProcessClickGoSecForm(bool);
void doProcessSecFormRequest(QString);
private:
Ui::FirstForm *ui;
SecForm t1;
SecForm *pot2;
void Init();//声明方法
};
#endif // FIRSTFORM_H
#ifndef SECFORM_H
#define SECFORM_H
#include <QWidget>
#include "thdform.h"
namespace Ui {
class SecForm;
}
class SecForm : public QWidget
{
Q_OBJECT
public:
explicit SecForm(QWidget *parent = 0);
~SecForm();
private slots:
void doProcessClickBack1(bool);
void doProcessGoThdForm(bool);
void doProcessShow();
signals:
void SignalShowFirstForm(QString);
private:
Ui::SecForm *ui;
int clickCount;
ThdForm *pot3;
void Init();
};
#endif // SECFORM_H
#ifndef THDFORM_H
#define THDFORM_H
#include <QWidget>
#include <QTimer>
namespace Ui {
class ThdForm;
}
class ThdForm : public QWidget
{
Q_OBJECT
public:
explicit ThdForm(QWidget *parent = 0);
~ThdForm();
private slots:
void doProcessTimeOut();//超时信号处理
void doProcessBack2();
signals:
void SignalShowSecForm();
private:
Ui::ThdForm *ui;
int count;//全局计时
QTimer *myTimer;
void Init();//初始化对象
};
#endif // THDFORM_H
3个源文件代码如下:(*.cpp)
#include "firstform.h"
#include "ui_firstform.h"
#include <QMovie>
#include <qDebug>
FirstForm::FirstForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::FirstForm)
{
ui->setupUi(this);
Init();//调用
//绑定:处理1号窗体单击事件
connect(ui->pushButton,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickGoSecForm(bool)));
}
FirstForm::~FirstForm()
{
delete ui;
}
【Function】
void FirstForm::Init(){
//动画显示
QMovie *movie = new QMovie("../0528Form2Form/Big.gif");//加载文件:注意目录的斜杠方向(是/)(不是\)//..表示当前文件的上级目录。完整目录E:/QtCode/0528Form2Form/Big.gif
movie->start();//动起来
ui->label->setMovie(movie);//固定位置
ui->label->setScaledContents(true);//缩放内容
//处理单击事件:跳转到第二页面
connect(ui->pushButton,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickGoSecForm(bool)));
pot2 = new SecForm();//空间分配。注意:千万不要用this指针,否则会在父窗体中显示
//窗体1接收来自窗体2的信号
connect(pot2,SIGNAL(SignalShowFirstForm(QString)),
this,SLOT(doProcessSecFormRequest(QString)));
}
【Slots】
void FirstForm::doProcessClickGoSecForm(bool){
//创建第2个窗体,记得在头文件中引入第2个页面的头文件
//(对象形式用全局变量;指针形式用局部变量或全局变量的比较)
//【1】第一种方式:指针形式(局部),会出现多个第2页面(因为每次都new,会创建多个窗体)
// SecForm *tf1 = new SecForm(this);//指针形式(有this,子窗体将在父窗体中直接显示)
// tf1->show();
// SecForm *tf1 = new SecForm();//指针形式:出现多个第2页面(无this,是并列窗体)
// tf1->show();//指针形式:每次都new,会创建多个窗体 (new的意思就是“创建”)
//【2】第二种方式:t1全局变量————只创建1个窗体(与局部变量做对比)
// SecForm t1;//仿照main.cpp,t1是局部变量
// t1.show();//这种方式行不通,因为资源是局部的,一开始就释放掉了。在该函数内部执行完,就没了。
// //头文件中定义全局变量 SecForm t1;//全局变量
// t1.show();//全局变量t1,只创建1个窗体
//【3】第三种方式:把指针定义为全局的(只new一个对象)————一开始就分配好空间 pot2 = new SecForm();
pot2->show(); // 头文件中定义全局指针 SecForm *pot2;
this->hide();//隐藏当前页面
}
void FirstForm::doProcessSecFormRequest(QString str){
qDebug()<< str <<endl;//打印:单击了几次返回。
this->show();//请求:显示当前页面
}
#include "secform.h"
#include "ui_secform.h"
#include <QMovie>
SecForm::SecForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecForm)
{
ui->setupUi(this);
Init();
}
SecForm::~SecForm()
{
delete ui;
}
/【Function】/
void SecForm::Init(){
clickCount = 0;//清空(按钮点击次数)
//动画显示
QMovie *movie = new QMovie("../0528Form2Form/jump.gif");//加载文件:注意目录的斜杠方向(是/)(不是\)//..表示当前文件的上级目录。完整目录E:/QtCode/0528Form2Form/Big.gif
movie->start();//动起来
ui->label->setMovie(movie);//固定位置
ui->label->setScaledContents(true);//缩放内容
//绑定
connect(ui->Back1,SIGNAL(clicked(bool)),
this,SLOT(doProcessClickBack1(bool)));
pot3 = new ThdForm();//分配空间
connect(ui->Next3,SIGNAL(clicked(bool)),
this,SLOT(doProcessGoThdForm(bool)));
connect(pot3,SIGNAL(SignalShowSecForm()),
this,SLOT(doProcessShow()));
}
/【Slots】/
void SecForm::doProcessClickBack1(bool){
clickCount++; //每点击一次,就++
//窗体2发射信号,通知第1个窗体显示。统计点击了多少次(发射了多少次信号) //窗体1接收信号
emit SignalShowFirstForm(QString::number(clickCount)); //number:把int转换为QString类型
this->hide();//发射信号被处理后,第2窗体把自己隐藏
}
void SecForm::doProcessGoThdForm(bool){
pot3->show();//【下一页】显示第3个窗体
this->hide();//隐藏自己
}
void SecForm::doProcessShow(){
this->show();//【返回第二页面】显示
}
#include "thdform.h"
#include "ui_thdform.h"
ThdForm::ThdForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ThdForm)
{
ui->setupUi(this);
Init();//调用初始化对象的函数
}
ThdForm::~ThdForm()
{
delete ui;
}
/【Function】/
void ThdForm::Init(){
count = 0;
//LCD
myTimer = new QTimer(this);//分配空间,对象释放this
connect(myTimer,SIGNAL(timeout()),
this,SLOT(doProcessTimeOut()));
myTimer->start(100);//让时间跑起来:100ms一次
connect(ui->Back2,SIGNAL(clicked(bool)),
this,SLOT(doProcessBack2()));
}
/【Slots】/
void ThdForm::doProcessTimeOut(){
count++;
if(count == 100)
count =0;
ui->lcdNumber->display(count);
}
void ThdForm::doProcessBack2(){
//第3窗体给第2窗体发送信号,通知2号窗体显示————第2窗体接收信号
emit SignalShowSecForm();
this->hide();
}