【Qt】深入探索Qt主窗口与菜单栏:构建高效用户界面的实践指南

文章目录

  • 前言
  • 1. 什么是Main Window?
  • 2. 详细了解一下其中的 菜单栏:
    • 2.1. 创建菜单栏
    • 2.2. 添加快捷键
    • 2.3. 添加子菜单
    • 2.4. 添加分割线
    • 2.5. 添加图标
  • 3. 内存泄漏问题:
  • 总结

前言

在现代软件开发中,用户界面的设计对于提升用户体验至关重要。Qt框架作为功能强大的跨平台开发工具,提供了丰富的组件和工具来帮助开发者构建复杂的应用程序。本文将深入探讨Qt中的主窗口(QMainWindow)及其菜单栏(QMenuBar)的创建和使用,包括菜单栏的创建、菜单项的添加、快捷键的设置、子菜单的嵌套、分割线的使用以及图标的添加。此外,文章还将讨论内存泄漏问题,以及如何在Qt中避免这类问题,确保应用程序的稳定性和性能。
前面学习的所有代码,都是基于 QWidget(控件),QWidget 更多的是作为别的窗口的一个部分。

1. 什么是Main Window?

QMainWindow 是⼀个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了⼀个预定义的布局。QMainWindow 包含 ⼀个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为 QMainwindow 中 各组件所处的位置:
在这里插入图片描述

  • 菜单栏(Menu Bar):
    Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。⼀个主窗口最多只有⼀个菜单栏。位于主窗口顶部、主窗口标题栏下面。
    在这里插入图片描述

  • 工具栏(Tool Bar Area):
    工具具栏是应用程序中集成各种功能实现快捷键使用的⼀个区域。可以有多个,也可以没有,它并不是应用程序中必须存在的组件。它是⼀个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。如下图为工具栏的示意图:
    在这里插入图片描述

  • 铆接部件/子窗口(Dock Widget Area)
    一个主窗口往往可以是由多个子窗口所构成的。
    在这里插入图片描述

  • 中央控件(Central Widget)
    窗口最核心的部分
    在这里插入图片描述

  • 状态栏(Status Bar)
    用于显示一些信息供用户去参考。
    在这里插入图片描述

2. 详细了解一下其中的 菜单栏:

Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。⼀个主窗口最多只有⼀个菜单栏。位于主窗口顶部、主窗口标题栏下面。
菜单栏中包含菜单. 菜单中包含菜单项。
在这里插入图片描述

一个主窗口最多只有一个菜单栏,工具栏,本质上就是菜单中的一些选项的“快捷方式”
QAction 动作

2.1. 创建菜单栏

“在这里输入” 可以在这里添加菜单了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

菜单栏(QMenuBar) -> 菜单(QMenu) -> 菜单项(QAction

在这里插入图片描述
由于当前每个菜单都是空着的,点上去没反应,添加后有反应。
在这里插入图片描述
使用代码去创建菜单结构:

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先创建一个菜单栏QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 创建菜单QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("编辑");QMenu* menu3 = new QMenu("视图");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 给菜单添加菜单项QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打开");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存为");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);}MainWindow::~MainWindow()
{delete ui;
}

在这里插入图片描述
怎样使它点击的时候有反应呢?

QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("保存");
QAction* action4 = new QAction("另存为");
QAction* action5 = new QAction("退出");

被点击的时候会触发一个信号!triggered 触发

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先创建一个菜单栏QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 创建菜单QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("编辑");QMenu* menu3 = new QMenu("视图");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 给菜单添加菜单项QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打开");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存为");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);// 4. 给 action 添加信号槽connect(action1, &QAction::triggered, this, &MainWindow::handle);connect(action5, &QAction::triggered, this, &MainWindow::close); // close 是Qt自带关闭窗口的槽函数}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{qDebug() << "触发新建操作!";
}

在这里插入图片描述

2.2. 添加快捷键

给菜单和菜单项设置快捷键
设置好的快捷键就可以搭配 alt 来进行使用了

QMenu* menu1 = new QMenu("文件(&F)");

通过给文本添加 &F 这样的操作,就是添加了快捷键 alt+F
与,QLabel,中设置伙伴的方式比较相似,当然使用 QShortcut 也可以实现同样的效果但是太麻烦了。
在这里插入图片描述
给菜单项同样可以添加快捷键:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menBar = new QMenuBar();this->setMenuBar(menBar);QMenu* menu1 = new QMenu("文件(&F)");QMenu* menu2 = new QMenu("视图(&V)");menBar->addMenu(menu1);menBar->addMenu(menu2);// 创建四个菜单项QAction* action1 = new QAction("action1(&Q)");QAction* action2 = new QAction("action2(&W)");QAction* action3 = new QAction("action3(&E)");QAction* action4 = new QAction("action4(&R)");menu1->addAction(action1);menu1->addAction(action2);menu2->addAction(action3);menu2->addAction(action4);// 如果不绑定槽函数,通过快捷键选中也没啥反应connect(action1, &QAction::triggered, this, &MainWindow::handle1);connect(action2, &QAction::triggered, this, &MainWindow::handle2);connect(action3, &QAction::triggered, this, &MainWindow::handle3);connect(action4, &QAction::triggered, this, &MainWindow::handle4);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle1()
{qDebug() << "handle1" ;
}void MainWindow::handle2()
{qDebug() << "handle2" ;
}void MainWindow::handle3()
{qDebug() << "handle3" ;
}void MainWindow::handle4()
{qDebug() << "handle4" ;
}

2.3. 添加子菜单

菜单栏 -> 菜单 -> 菜单项
菜单栏->菜单->子菜单->菜单项

QMenuBar 可以通过 addMenu 添加菜单的,QMenu 也提供了 addMenu

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menuParent = new QMenu("父菜单");QMenu* menuChild = new QMenu("子菜单");menuBar->addMenu(menuParent);menuParent->addMenu(menuChild);QAction* action1 = new QAction("菜单项1");QAction* action2 = new QAction("菜单项2");menuChild->addAction(action1);menuChild->addAction(action2);QMenu* menuChild2 = new QMenu("子菜单2");menuChild->addMenu(menuChild2);}MainWindow::~MainWindow()
{delete ui;
}

在这里插入图片描述

2.4. 添加分割线

菜单里菜单特别多,就可以通过分割线进行分组

QMenu 中提供了 addSeparator 这样的函数

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜单");menuBar->addMenu(menu);QAction* action1 = new QAction("菜单项1");QAction* action2 = new QAction("菜单项2");menu->addAction(action1);menu->addSeparator();menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}

在这里插入图片描述

2.5. 添加图标

Qlcon 类, qrc

在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜单");menuBar->addMenu(menu);QAction* action1 = new QAction("菜单项1");action1->setIcon(QIcon(":/open.png"));QAction* action2 = new QAction("菜单项2");action2->setIcon(QIcon(":/save.png"));menu->addAction(action1);menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}

在这里插入图片描述
如果给 QMenu 设置图标,当前 QMenu 是长在 QMenuBar 上的,此时文本就不显示,图标就覆盖了文本。

QMenu 是子菜单,图标和文本都是能显示的。

3. 内存泄漏问题:

QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);

如果咱们创建项目,没有勾选生成ui,文件,此时上述代码是可以的,如果勾选了自动生成 ui 文件,上述代码则会引起内存泄漏。
自动生成 ui 文件:Qt已经给你生成了一个 QMenuBar 了。

之前程序已经创建好了一个 QMenuBar , 当设置新的 QMenuBar 进来的时候, 就会导致旧的 QMenuBar 脱离了 Qt 的对象树了,意味着后续无法对这个对象树进行释放了

上诉程序如果窗口关闭,对象树释放,此时进程也就介绍了。进程结束,自然所有内存都回收给系统。上述内存泄漏也不会造成影响,但是如果这样的如果出现在一个多窗口的程序中。如果涉及到窗口的频繁跳转切换(窗口的频繁创建销毁),上述代码泄漏会更严重一些。但是实际上由于现在的计算机内存都比较充裕上述内存泄漏都还好。

服务器程序相比于客户端程序相比更害怕内存泄漏。

  1. 服务器要处理很多请求,每个请求泄漏一点,请求累积下来就会泄漏很多
  2. 服务器要 7 * 24 小时运行。

当然,即使如此,还是期望代码写的更规范一些。

QMenuBar* menuBar = this->menuBar();
  1. 如果 QMenuBar 已经存在,直接获取并返回
  2. 如果 QMenuBar 不存在,就先创建一个新的,再返回。
this->setMenuBar(menuBar);

如果是活的已经存在的 QMenuBar, 这里的设置就是自己替换自己,仍然对象树上

如在嵌入式,设备上内存泄漏的问题就比较重要了。

总结

本文详细介绍了Qt中主窗口(QMainWindow)的构成和功能,特别是菜单栏(QMenuBar)的创建和使用。通过一系列具体的代码示例,我们学习了如何创建菜单栏、添加菜单和菜单项、设置快捷键、嵌套子菜单、使用分割线以及添加图标,这些都是构建用户友好界面的关键步骤。同时,文章也指出了在Qt开发中可能遇到的内存泄漏问题,并提供了解决方案,强调了在开发过程中遵循良好编程实践的重要性。通过这些知识点,开发者可以更有效地利用Qt框架,创建出既美观又实用的应用程序界面。

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

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

相关文章

【雅特力AT32】串口UART、USART配置和使用方法,数组的阻塞发送函数编写,串口接收中断、回环、重定向

【雅特力AT32】串口UART、USART配置和使用方法&#xff0c;数组的阻塞发送函数编写&#xff0c;串口接收中断、回环、重定向 文章目录 串口配置阻塞发送函数接收中断和串口回环串口重定向附录&#xff1a;Cortex-M架构的SysTick系统定时器精准延时和MCU位带操作SysTick系统定时…

ARM|DSP+FPGA+NVIDIA AI摄像头定制

信迈拥有高性能的摄像头全栈能力&#xff1a;掌握车载模组光学设计能力&#xff0c;具有多名经验丰富光学设计专家&#xff1b;具备丰富的车载摄像模组硬件设计经验&#xff1b;掌握目前市面上大部分车载平台的ISP图像画质服务能力&#xff0c;能自主开发图像ISP和增强算法&…

第十二章 网络编程

第十二章 网络编程 网络协议概述 通信协议&#xff1a; 协议即规则&#xff0c;就好比汽车上路要遵守交通规则一样&#xff0c;为了使全世界不同类型的计算机都可以连接起来&#xff0c;所以制定了一套全球通用的通信协议——Internet协议。有了Internet协议&#xff0c;任何…

【mysql】【docker】mysql8-互为主从

&#x1f338;&#x1f338; Linux/docker-compose/mysql8 互为主从 优雅部署 &#x1f338;&#x1f338; 记录下两台Linux的mysql需要热备份&#xff0c;互为主从&#xff0c;后期加上keepalived实现高可用切换 参考博客&#xff1a;答 案 &#x1f338; 一、准备文件 这里…

图形学初识--直线插值算法

文章目录 为什么需要插值算法&#xff1f;插值算法是什么&#xff1f;有哪些常见的插值算法呢&#xff1f;1. 线性插值&#xff08;Linear Interpolation&#xff09;2. 多项式插值&#xff08;Polynomial Interpolation&#xff09;3. 样条插值&#xff08;Spline Interpolati…

Blazor 下支持 Azure AD 的多套登录方案

比如上图配置了两套不同的登录方案&#xff0c;各有自己的 TenantId 和 ClientId &#xff0c;要同时支持他们的登录&#xff08;其实在同一套 TenantId 和 ClientId 里面配置多个登录账户不就好了&#xff0c;但是......那套登录的管理是在客户自己的Azure AD账户管理下的&…

SpringBoot3 解决NoResourceFoundException: No static resource favicon.ico.异常

SpringBoot3 解决NoResourceFoundException: No static resource favicon.ico.异常 spring boot3项目中浏览器中访问报错找不到favicon.ico&#xff0c;虽然不影响使用&#xff0c;用api工具也可以忽略这个异常&#xff0c;但是防止浏览器访问时出现异常干扰日志&#xff0c;所…

oracle数据库解析过高分析

解析非常高&#xff0c;通过时间模型可以看到解析占比非常高 解析大致可以分为硬解析&#xff08; hard parse&#xff09;、软解析&#xff08; soft parse&#xff09;和软软解析&#xff08; soft soft parse&#xff09;。如&#xff0c;执行一条 SQL 的时候&#xff0c;如…

Google Find My Device:科技守护,安心无忧

在数字化的时代&#xff0c;我们的生活与各种智能设备紧密相连。而 Google Find My Device 便是一款为我们提供安心保障的实用工具。 一、Find My Decice Netword的定义 谷歌的Find My Device Netword旨在通过利用Android设备的众包网络的力量&#xff0c;帮助用户安全的定位所…

STM32F4_HAL控制GPIO输出——跑马灯实验

1、GPIO工作模式 1.1 端口输入数据寄存器&#xff08;IDR&#xff09; 1.2 端口输出数据寄存器&#xff08;ODR&#xff09; 1.3 端口置位/复位寄存器&#xff08;BSRR&#xff09; 为什么有了 ODR 寄存器&#xff0c;还要这个 BSRR 寄存器呢&#xff1f;我们先看看 BSRR 的寄…

23种设计模式(持续输出中)

一.设计模式的作用 设计模式是软件从业人员长期总结出来用于解决特定问题的通用性框架&#xff0c;它提高了代码的可维护性、可扩展性、可读性以及复用性。 二.设计模式 1.工厂模式 工厂模式提供了创建对象的接口&#xff0c;而无需制定创建对象的具体类&#xff0c;工厂类…

华为OD机试 - 剩余银饰的重量(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

【Python】 如何对对象列表进行排序,有点意思

在Python中&#xff0c;我们经常需要对对象列表进行排序&#xff0c;这可以通过多种方式实现。当对象是一个自定义类实例时&#xff0c;排序通常基于对象的一个或多个属性。Python提供了内置的sorted()函数和列表的sort()方法&#xff0c;它们都允许我们指定一个排序的关键字。…

iPhone彻底删除的照片怎么恢复?专业技巧助您解忧

在使用iPhone的过程中&#xff0c;我们可能会因为误操作或其他原因将一些重要的照片彻底删除。然而&#xff0c;即使照片被彻底删除&#xff0c;也并不意味着它们就永远消失了&#xff0c;它们只是被打上了“可覆盖的空间”的标签。 在照片被新数据覆盖之前&#xff0c;我们仍…

C语言学习【C控制语句:循环】

C语言学习【C控制语句&#xff1a;循环】 while循环 /* 根据用户键入的整数求和 */#include "stdio.h"int main(void) {long num;long sum 0L; /* 把sum初始化为0 */int status;printf("Please enter an integer to be summed");printf(&quo…

基于微信小程序的校园捐赠系统的设计与实现

校园捐赠系统是一种便捷的平台&#xff0c;为校园内的各种慈善活动提供支持和便利。通过该系统&#xff0c;学生、教职员工和校友可以方便地进行捐赠&#xff0c;并了解到相关的项目信息和捐助情况。本文将介绍一个基于Java后端和MySQL数据库的校园捐赠系统的设计与实现。 技术…

快速开发 Chrome插件

什么是 Chrome 插件 Chrome 插件程序是一种用于增强 Google Chrome 浏览器功能的小型软件应用程序。它们可以帮助用户自定义浏览体验、添加新功能、集成外部服务以及自动化任务等。扩展程序使用 HTML、CSS 和 JavaScript 编写&#xff0c;利用 Chrome 提供的 API 来与浏览器及…

18.分布式监控zabbix-proxy

zabbix proxy 使用场景: 监控远程区域设备监控本地网络不稳定区域当 zabbix 监控上千设备时,使用它来减轻 server 的压力简化分布式监控的维护 环境规划&#xff1a; zabbix-server&#xff1a;外网IP地址192.168.111.66 zabbix-proxy:外网IP地址192.168.111.11 内网IP地址…

AI工具推荐:提升工作效率与生活质量

有哪些好用&#xff0c;且国内可用的AI工具&#xff1f; 副本 在AI大发展的年代&#xff0c;还有人在工作、生活中没有使用过AI吗&#xff1f; 今天为大家推荐几款国内可用、好用的AI工具&#xff0c;不论是自媒体文案写作、打工人汇报PPT、还是论文、公文写作&#xff0c;总…

设计系统采购与安装:乙级资质申请的技术准备

在设计系统采购与安装方面&#xff0c;为乙级资质申请所做的技术准备涉及多个方面。以下是一些关键的技术准备事项&#xff1a; 明确技术需求&#xff1a;首先&#xff0c;需要明确乙级资质申请所需的技术系统类型和规格。这可能包括但不限于设计软件、工程管理系统、项目管理系…