QT系列教程(4) Qt 信号和槽

信号和槽

当我们需要一个界面通知另一个界面时,可以采用信号和槽机制。通过链接信号和槽,当一个界面发送信号时,链接该信号的槽会被响应,从而达到消息传递的目的。
所以我们先创建一个Qapplication Widgets 应用。Creator会为我们生成mainwindow类和其界面。我们在界面添加一个按钮,按钮的名字叫showChildButton, 按钮显示的文字改为“显示子界面”。
同时为该界面添加一个label,显示的文字修改为“这是主界面”

https://cdn.llfc.club/EBD5635CE2FA.png
现在实现点击按钮,在控制台打印一条日志 "show child dialog "
我们先在MainWindow的构造函数中添加信号和槽的链接逻辑

connect(ui->showChildButton, SIGNAL(clicked(bool)), this, SLOT(showChildDialog()));

然后我们为MainWindow添加showChildDialog槽函数,槽函数需要用slots声明,我们这里在mainwindow.h里用public slots的方式声明槽函数。

public slots:void showChildDialog();

接下来去mainwindow.cpp中完成该函数的实现,可以在头文件中右键该函数,在弹出菜单里选择Refactor, 再选择在mainwindow.cpp中添加实现。
https://cdn.llfc.club/645C3ED1042D.png
也可以将鼠标光标放置在这个函数上,按alt+enter,弹出菜单选择在mainwindow.cpp中添加实现。这两种方式都是快捷添加,也可以直接去mainwindow.cpp里实现。

void MainWindow::showChildDialog()
{qDebug() << "show child dialog " << endl;
}

运行项目后点击按钮,就可以看到控制台弹出show child dialog日志。

不同的连接方式

我们上边用来连接信号和槽的方式是qt4提供的方式,用SIGNAL和SLOT将信号和槽转化为字符串。
但是这种方式会存在一定问题,Qt要求槽函数的参数不能超过信号定义的参数,比如我们用到的信号clicked(bool)参数就是bool,我们定义的槽函数showChildDialog()是不带参数的,可以连接成功,如果我们在连接的时候将showChildDialog的参数写为3个,也可以连接成功

 //qt4 风格的Slot和Signal 只是宏转换,字符串定义不能检测编译错误connect(ui->showChildButton, SIGNAL(clicked(bool)), this, SLOT(showChildDialog(1,2,3)));

但是点击会没有反应,说明qt4 这种连接信号和槽的方式不做编译检查,只是将信号和槽函数转译成字符串。
所以我推荐使用qt5以上版本的连接方式

 //推荐qt5 风格
connect(ui->showChildButton, &QPushButton::clicked, this, &MainWindow::showChildDialog);

这种方式也可以实现信号和槽函数的连接。

实现界面的切换

我们现在实现这样一个demo,程序启动后弹出主界面,点击主界面的按钮弹出子窗口,隐藏主界面,点击子窗口界面的按钮,隐藏子界面,显示主窗口。
所以我们右击项目弹出菜单选择创建Qt设计师界面类,选择Dialog without Buttons,

https://cdn.llfc.club/1661563857494.jpg

名字选择ChildDialog

https://cdn.llfc.club/1661563857494.jpg

我们进入子界面的ui设计界面,添加一个label 描述为这是子界面,添加一个PushButton,文字修改为显示主窗口,并且将按钮的名字修改为showMainWindow
https://cdn.llfc.club/1661736849837.jpg

Qt会为我们创建一个界面类名字叫ChildDialog,我们可以将其作为MainWindow类的成员

class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
public slots:void showChildDialog();
private:ChildDialog *_child_dialog;
};

然后重新改写槽函数,使点击按钮后弹出对话框

void MainWindow::showChildDialog()
{qDebug() << "show child dialog " << endl;auto _child_dialog = new ChildDialog(this);_child_dialog->show();
}

再次运行程序点击显示子界面的按钮,就会弹出子界面了。关闭子界面,再次点击主窗口的显示子窗口按钮,子窗口又显示出来。
这么做有一个问题就是可能会重复创建子窗口,但是Qt的对象树机制会保证父窗口回收时才回收子窗口,所以关闭子窗口只是隐藏了。
那么随着点击,久而久之窗口会越来越多。
我们想到的一个避免重复创建的办法就是在MainWindow的构造函数里创建好子界面,在槽函数中只控制子界面的显示即可。
但同时要注意在MainWindow的析构函数里回收子界面类对象。

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);_child_dialog = new ChildDialog(this);connect(ui->showChildButton, &QPushButton::clicked, this, &MainWindow::showChildDialog);
}MainWindow::~MainWindow()
{delete ui;if(_child_dialog){delete  _child_dialog;_child_dialog = nullptr;}
}void MainWindow::showChildDialog()
{qDebug() << "show child dialog " << endl;_child_dialog->show();
}

这样我们频繁点击显示子界面按钮就不会重复创建窗口了。
那接下来实现点击主界面的按钮,显示子界面,并隐藏主窗口。
实现点击子界面的按钮,显示主窗口,并隐藏子界面。
先实现点击子界面按钮显示主窗口,我们可以在ChildDialog类修改下构造函数,使其接受一个QWidget指针,这个指针指向父窗口也就是MainWindow.
我们新增成员_parent用来存储MainWindow。
新增槽函数showMainWindow用来显示主窗口。

class ChildDialog : public QDialog
{Q_OBJECT
public:explicit ChildDialog(QWidget *parent = nullptr);~ChildDialog();private:Ui::ChildDialog *ui;QWidget *_parent;
public slots:void showMainWindow();};

在ChildDialog的实现文件里连接槽函数,并且实现子界面隐藏,主界面显示

ChildDialog::ChildDialog(QWidget *parent) :QDialog(parent),ui(new Ui::ChildDialog),_parent(parent)
{ui->setupUi(this);connect(ui->showMainWindow, &QPushButton::clicked, this, &ChildDialog::showMainWindow);
}void ChildDialog::showMainWindow()
{qDebug() << "show main window" << endl;_parent->show();this->hide();
}

修改主界面的槽函数,让主界面隐藏,子界面显示

void MainWindow::showChildDialog()
{qDebug() << "show child dialog " << endl;_child_dialog->show();this->hide();
}

运行程序后,点击按钮就可以实现界面的切换。
这么做有一个不好的地方就是在ChildDialog类里保存了MainWindow的指针,如果我们ChildDialog类里要实现和多个其他界面的交互,就需要保存多个指针,这样代码的耦合性太大了。所以我们引入信号和槽机制,当我们点击子界面按钮时发送一个信号给主界面,这样主界面收到该信号后就显示主界面隐藏子界面。
那我们先为ChildDialog类声明一个信号,用来通知主界面显示

class ChildDialog : public QDialog
{Q_OBJECT
signals:void showMainSig();
public:explicit ChildDialog(QWidget *parent = nullptr);~ChildDialog();private:Ui::ChildDialog *ui;QWidget *_parent;
public slots:void showMainWindow();
};

showMainSig是一个信号,用来通知主界面,所以主界面MainWindow类要连接这个信号,我们先在主界面类中声明这个函数

class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
public slots:void showChildDialog();void showMainDialog();
private:ChildDialog *_child_dialog;
};

showMainDialog 是新增的槽函数,用来连接ChildDialog的showMainSig信号。
我们修改ChildDialog的showMainWindow函数

void ChildDialog::showMainWindow()
{qDebug() << "show main window" << endl;this->hide();//可以再次发送信号通知主窗口显示emit showMainSig();
}

然后在MainWindow连接这个信号

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);_child_dialog = new ChildDialog(this);//推荐qt5 风格connect(ui->showChildButton, &QPushButton::clicked, this, &MainWindow::showChildDialog);connect(_child_dialog, &ChildDialog::showMainSig, this, &MainWindow::showMainDialog);
}void MainWindow::showChildDialog()
{qDebug() << "show child dialog " << endl;_child_dialog->show();this->hide();
}

再次运行程序,点击按钮实现了界面的切换。

连接信号

上面的程序还可以进一步优化,因为Qt提供了信号连接信号的方式,也就是说我们可以把子界面的按钮点击信号和showMainSig信号连接起来。

ChildDialog::ChildDialog(QWidget *parent) :QDialog(parent),ui(new Ui::ChildDialog),_parent(parent)
{ui->setupUi(this);connect(ui->showMainWindow, &QPushButton::clicked, this, &ChildDialog::showMainSig);
}

将clicked和showMainSig两个信号连接起来,也可以实现消息的传递,让代码更简洁了。

总结

视频链接视频教程
源码链接https://gitee.com/secondtonone1/qt-learning-notes

owMainSig两个信号连接起来,也可以实现消息的传递,让代码更简洁了。

总结

视频链接视频教程
源码链接https://gitee.com/secondtonone1/qt-learning-notes

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/610413.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue实现的艺术水平考级报名管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

前端开发攻略---Vue通过自定义指令实现元素平滑上升的动画效果(可以自定义动画时间、动画效果、动画速度等等)。

1、演示 2、介绍 这个指令不是原生自带的&#xff0c;需要手动去书写&#xff0c;但是这辈子只需要编写这一次就好了&#xff0c;后边可以反复利用。 3、关键API IntersectionObserver IntersectionObserver 是一个用于监测元素是否进入或离开视口&#xff08;viewport&#x…

系统开发实训小组作业week7 —— 优化系统开发计划

目录 1. 建立规则&#xff0c;仪式&#xff0c;流程&#xff0c;模式 2. 给好行为正面的反馈 3. 明确指出不合适的行为&#xff0c;必要时调整人员 在 “系统开发实训课程” 中&#xff0c;我们小组的项目是 “电影院会员管理系统” 。在项目的开发过程中&#xff0c;我们遇…

AIGC革新浪潮:大语言模型如何优化企业运营

在当今快速发展的商业环境中&#xff0c;企业对于有效管理知识资产的需求日益增长。知识管理作为企业核心竞争力的关键组成部分&#xff0c;对于提高决策质量、增强创新能力和优化运营流程起着至关重要的作用。随着数字化转型的推进&#xff0c;企业对知识管理系统提出了新的要…

2024.4.11

1.思维导图 2.指针形式验证大小端存储 #include<myhead.h>int main(int argc, const char *argv[]) {int num 0x12345678;char* ptr (char *)&num;if(*ptr 0x12){printf("big endian\n");}else if(*ptr 0x78){printf("little endian\n");}r…

汉字人民币转阿拉伯数字

先看结果&#xff1a; 废话不多说 直接上代码&#xff1a; package com.ht.commons;import java.math.BigDecimal; import java.util.HashMap; import java.util.Map;public class ChineseRMBConverter {private static final Map<Character, BigDecimal> numMap new H…

探讨解决emp.dll文件丢失问题的步骤和方法,一键解决emp.dll丢失烦恼问题

在电脑使用过程中&#xff0c;有时会遇到提示emp.dll文件丢失的错误弹窗&#xff0c;这种情形通常由于某些误操作或问题导致emp.dll文件出现异常。面对这样的状况&#xff0c;可以采取以下几种方法来解决emp.dll文件缺失的问题。接下来&#xff0c;让我们共同探讨解决emp.dll文…

D盘格式化了能正常使用吗 D盘格式化了数据怎么恢复 d盘格式化后安装不了软件怎么办 easyrecovery数据恢复软件

今天本文就为大家解决D盘格式化了能正常使用吗和D盘格式化了数据怎么恢复的硬盘格式化问题。 一、D盘格式化了能正常使用吗 通常我们所说的格式化硬盘操作是为硬盘做初始化的工作&#xff0c;以便能够抹掉老数据&#xff0c;重新写入新数据。格式化后的D盘&#xff0c;虽然其…

关于HTTP1.0、1.1、1.x、2.0、3.0与HTTPS之间的理解

关于HTTP1.0、1.1、1.x、2.0、3.0与HTTPS之间的理解 HTTP的由来 HTTP是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写。它的发展是万维网协会&#xff08;World Wide Web Consortium&#xff09;和Internet工作小组IETF&#xff08;Internet Eng…

用友NC open SQL注入漏洞复现(XVE-2023-29119)

0x01 产品简介 用友NC是由用友公司开发的一套面向大型企业和集团型企业的管理软件产品系列。这一系列产品基于全球最新的互联网技术、云计算技术和移动应用技术,旨在帮助企业创新管理模式、引领商业变革。 0x02 漏洞概述 用友NC /portal/pt/PaWfm/open接口的proDefPK参数存…

如何将普通maven项目转为maven-web项目

文件-项目结构&#xff08;File-->Project Structure &#xff09; 模块-->learn&#xff08;moudle-->learn&#xff09; 选中需要添加web的moudle&#xff0c;点击加号&#xff0c;我得是learn&#xff0c;单击选中后进行下如图操作&#xff1a; 编辑路径 结果如下…

乡村振兴多元共治,共绘乡村新蓝图:政府引领、企业助力、村民参与

乡村振兴是一项复杂而艰巨的任务&#xff0c;需要从多个角度进行考虑。以下是从不同身份出发对乡村振兴建设的思考&#xff1a; 1、政府领导的角度&#xff1a; 政府是乡村振兴的主要推动者和组织者。在制定和实施乡村振兴战略时&#xff0c;政府需要注重规划引领&#xff0c;科…