【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框架,创建出既美观又实用的应用程序界面。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

秀某动预约抢票脚本

秀某动预约抢票脚本 小白操作-仅供学习参考 主要流程和功能 初始化和配置变量: confirm_url 和 login_url: 分别存储登录和确认订单的URL。 wait_time: 用户输入的提前多少秒开始执行。 start_time: 开售时间。 DEBUG: 调试标志&#xff0c;用于控制脚本的行为。 浏览…

并网逆变器学习笔记9---VSG控制

参考文献&#xff1a;《新型电力系统主动构网机理与技术路径》 “构网技术一般包含下垂控制&#xff0c;功率同步控制&#xff0c;虚拟同步机控制&#xff0c;直接功率控制&#xff0c;虚拟振荡器控制 等。其中&#xff0c;虚拟同步机技术&#xff0c;即 VSG&#xff0c;因其物…

css扇形菜单动画效果

菜单组件 IntelligentAnalysis.vue 中间圆形区域可以换个图片 <template><div class"intel-analysis"><div class"info" :class"{ close-animation: !showMenu }"><div class"middle"></div><div cl…

协变(List泛型作为方法参数时的父类子类问题)

有段时间没搞.net的项目了&#xff08;没办法&#xff0c;谁让国内JAVA流行是事实&#xff09;。最近又回归.net&#xff08;哪里需要哪里搬~&#xff09;。 接收到需求后&#xff0c;一顿输出&#xff0c;结果…咦?编译失败??? 错误信息&#xff1a; CS1503:参数1:无法…

阿里云 EMR Serverless Spark 版开启免费公测

阿里云 EMR Serverless Spark 版是一款云原生&#xff0c;专为大规模数据处理和分析而设计的全托管 Serverless 产品。它为企业提供了一站式的数据平台服务&#xff0c;包括任务开发、调试、调度和运维等&#xff0c;极大地简化了数据处理的全生命周期工作流程。使用 EMR Serve…

win11安装MySQL

目录[-] 1. 1. 下载2. 2. 安装 参考文档&#xff1a;MySQL :: MySQL 8.4 Reference Manual 1. 下载 mysql官网下载msi安装程序&#xff1a;MySQL :: Begin Your Download 2. 安装 运行下载的mis程序,逐步安装。 安装模式&#xff1a; complete; 进入配置&#xff1a; data di…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权&#xff0c;可以让你生成有洞察力的、 简洁的、易于理解的SEO报告&#xff0c;帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

苹果CMS:如何去掉首页帮助提示信息

首先我们安装好苹果CMS&#xff0c;未安装的可以参考苹果cms&#xff1a;介绍及安装 安装好之后我们需要进入模版设置&#xff0c;可能对于刚刚接触CMS框架的朋友是不清楚地址的&#xff1a; https://www.yourweb.com/admin_login.php/admin/mxpro/mxproset 其中【yourweb】…

探索移动云:我的ES与Kibana之旅

目录 引言&#xff1a; 如何免费体验移动云产品 登录并完成实名认证 选择试用ECS云主机 安全组配置 安装Elasticsearch和Kibana 安装Elasticsearch ​编辑安装kibana 测试结果 使用感觉 引言&#xff1a; 移动云技术产品的发展已经取得了巨大的进步。云数融合、A1、大…

宝塔面包安装搭建Flarum开源论坛程序 文档教程

一、服务器环境说明 宝塔 7.0.3 或更新版本 Linux Server&#xff08;本文用的是 CentOs 7.4.6 64位&#xff09; Apache 或者 Nginx&#xff08;本文用的是 Nginx 1.16.0&#xff09; MySQL 5.6&#xff08;本文使用 MySQL 5.7&#xff0c;原因请看下方引用&#xff09; PHP 7…

weblogic ssrf漏洞(CVE-2014-4210)

漏洞复现环境搭建请参考 Vulhub漏洞复现环境搭建流程_vulhub一键搭建漏洞测试靶场,来进行漏洞复现-CSDN博客 docker未能成功启动redis请参考 http://t.csdnimg.cn/5osP3 漏洞版本 weblogic 10.0.2 -- 10.3.6.0 漏洞验证 &#xff08;1&#xff09;访问7001端口&#xff0c;…

基于MetaGPT构建单智能体

前言 在之前的文章中&#xff0c;我们详细地描述了Agent的概念和组成&#xff0c;在代码案例中体验了Agent的记忆、工具、规划决策模块&#xff0c;并通过几个Agent框架来加强读者对Agent开发设计与应用的理解&#xff0c;接下来我们就要进入智能体Agent的实际开发中&#xff0…

Linux系统Redhat7.4版本安装mysql-5.7.17详细步骤

1.1、在根目录创建一个data目录 mkdir /data 1.2、将MySQL安装包上传到/data目录下 1.3、解压MySQL安装包到当前目录 tar -zxvf mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz 1.4、因为解压后MySQL目录名称太长&#xff0c;修改成简短的mysql mv mysql-5.7.17-linux-glibc2.…

AI智能体|扣子Coze“图像流”功能速览

大家好&#xff0c;我是无界生长。 AI智能体&#xff5c;扣子Coze“图像流”功能速览Coze提供易上手的图像处理工作流&#xff0c;包含智能生成、智能编辑和基础编辑三类节点&#xff0c;旨在通过AI技术简化图像处理过程。本文对扣子Coze“图像流”功能做了简单介绍&#xff0…

爬虫学习--11.MySQL数据库的基本操作(上)

MySQL数据库的基本操作 创建数据库 我们可以在登陆 MySQL 服务后&#xff0c;使用命令创建数据库&#xff0c;语法如下: CREATE DATABASE 数据库名; 显示所有的数据库 show databases; 删除数据库 使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删…

基于EifficientNet的视网膜病变识别

分析一下代码 model.py ①下面这个方法的作用是&#xff1a;将传入的ch&#xff08;channel&#xff09;的个数调整到离它最近的8的整数倍&#xff0c;这样做的目的是对硬件更加友好。 def _make_divisible(ch, divisor8, min_chNone):if min_ch is None:min_ch divisornew…

爬虫学习--12.MySQL数据库的基本操作(下)

MySQL查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 语法&#xff1a;在MySQL数据库中查询数据通用的 SELECT 语法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 条件] [LIMIT N] 查询语句中你可以使用一个或者多个表&…

Ajax用法总结(包括原生Ajax、Jquery、Axois)

HTTP知识 HTTP&#xff08;hypertext transport protocol&#xff09;协议『超文本传输协议』&#xff0c;协议详细规定了浏览器和万维网服务器之间互相通信的规则。 请求报文 请求行: GET、POST /s?ieutf-8...&#xff08;url的一长串参数&#xff09; HTTP/1.1 请求头…

MySQL数据库单表查询中查询条件的写法

1.使用比较运算符作为查询条件 ; !; >; >; <; <; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;字段 from 表名 where Gender “M”; 即挑选出Gender “M” 的教师&#xff0c; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;…

如何使用Android NDK将头像变成“遗像”

看完本文的标题&#xff0c;可能有人要打我。你说黑白的老照片不好吗&#xff1f;非要说什么遗像&#xff0c;我现在就把你变成遗像&#xff01;好了&#xff0c;言归正传。我想大部分人都用过美颜相机或者剪映等软件吧&#xff0c;它们的滤镜功能是如何实现的&#xff0c;有人…