深入浅出 Qt:QMainWindow 核心组件解析与 QDialog 对话框实战

发布时间:2026/9/30 7:16:45

深入浅出 Qt:QMainWindow 核心组件解析与 QDialog 对话框实战 个人主页Cx330❄️个人专栏《C语言》《LeetCode刷题集》《数据结构-初阶》《C知识分享》《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔《Git深度解析》:版本管理实战全解 《Qt 极境架构》MySQL 核心技术与实战心向往之行必能Cx330的简介目录前言一、 QMainWindow 的整体结构二、 菜单栏 (QMenuBar) 与 菜单项 (QAction)2.1 创建与使用2.2 实战示例1菜单栏 菜单 菜单项的基本使用2.3 实战示例2添加快捷键2.4 实战示例3添加子菜单2.5 实战示例4添加分割线和图标2.6 Qt 对象树与内存管理三. 工具栏Tool Bar常用功能快捷入口3.1 实战示例1创建工具栏(基本使用)3.2 实战示例2多个工具栏的使用四. 状态栏Status Bar状态信息展示区域4.1 实战示例多功能状态栏实时消息 文本 进度条 按钮五. 浮动窗口Dock Widget辅助功能承载区域5.1 实战示例浮动窗口的基本使用六. 核心组件避坑指南前言在 Qt 图形界面开发中QMainWindow是最常用的主窗口基类。它为开发者提供了一个标准的桌面应用程序窗口布局框架。本文将结合实际开发板书系统地讲解QMainWindow的五大构成区域以及QDialog对话框的核心用法。一、 QMainWindow 的整体结构QMainWindow预定义了一套完整的窗口布局结构主要包含以下五个部分-------------------------------------------------- | Menu Bar | -------------------------------------------------- | Tool Bar Area | ------------------------------------------------ | | | | | Dock Widget | Central Widget | Dock Widget | | Area | (核心工作区) | Area | | | | | ------------------------------------------------ | Status Bar | --------------------------------------------------菜单栏 (Menu Bar)位于窗口最上方包含一系列下拉菜单。工具栏 (Tool Bar Area)通常位于菜单栏下方可包含快捷按钮和常用控件支持拖拽停靠。浮动窗口/停靠窗口 (Dock Widget Area)围绕在中心部件周围的停靠面板。核心部件 (Central Widget)窗口中央的主要工作区域如文本编辑器、绘图区等。状态栏 (Status Bar)位于窗口最底部用于显示提示信息或当前状态。提示一个主窗口只能有一个菜单栏和一个状态栏但可以有多个工具栏和浮动窗口。二、 菜单栏 (QMenuBar) 与 菜单项 (QAction)2.1 创建与使用菜单栏通过QMenuBar实现而具体的菜单项由QMenu和QAction组成核心属性与 API菜单栏创建menuBar()QMainWindow 内置方法直接获取菜单栏对象或new QMenuBar(this)动态创建菜单创建new QMenu(“菜单名称”, this)通过menubar-addMenu(menu)添加到菜单栏菜单项创建new QAction(“菜单项名称”, this)通过menu-addAction(action)添加到菜单关键功能menu-addSeparator()添加分割线、action-setShortcut(QKeySequence(CtrlS))设置快捷键(还有别的方法看下面示例)核心信号QAction::triggered()菜单项被点击时触发。2.2 实战示例1菜单栏 菜单 菜单项的基本使用#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.给菜单项添加信号槽 connect(action1,QAction::triggered,this,MainWindow::handle); connect(action5,QAction::triggered,this,MainWindow::close); } MainWindow::~MainWindow() { delete ui; } void MainWindow::handle() { qDebug()触发新建操作!; }关键注意点菜单栏全局唯一多次调用setMenuBar()只会保留最后一个以及菜单栏的创建方式注意点2.3 实战示例2添加快捷键#include mainwindow.h #include ui_mainwindow.h #include QDebug MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); QMenuBar* menuBar new QMenuBar(); this-setMenuBar(menuBar); QMenu* menu1 new QMenu(文件(F)); QMenu* menu2 new QMenu(视图(V)); menuBar-addMenu(menu1); menuBar-addMenu(menu2); // 创建4个菜单项 QAction* action1 new QAction(action1(M)); QAction* action2 new QAction(action2(N)); 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; }关键注意点菜单项QAction可复用同时添加到菜单栏和工具栏无需重复创建后续会体现X格式的菜单名称用于设置AltX快捷键如F对应AltF打开文件菜单2.4 实战示例3添加子菜单#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.5 实战示例4添加分割线和图标#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(菜单); menu-setIcon(QIcon(:/open.png)); 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; }关键注意点分割线addSeparator()用于区分不同功能组如 “保存” 和 “退出” 之间提升可读性。2.6 Qt 对象树与内存管理在 Qt 中通过QObject的父子关系Object Tree管理对象生命周期当父对象析构时会自动调用所有子对象的析构函数。使用menuBar()或为QMenuBar指定this作为 Parent 时无需手动deleteQt 框架会自动进行内存释放。三. 工具栏Tool Bar常用功能快捷入口工具栏是菜单栏功能的 “快捷方式 集合”通常放置最常用的操作如新建、保存、复制支持自定义停靠位置、浮动、移动可多个共存灵活适配用户操作习惯。Qt 中通过QToolBar类实现依赖QAction作为快捷项。核心属性与 API创建方法new QToolBar(工具栏名称, this)通过addToolBar()添加到窗口停靠位置创建时指定addToolBar(Qt::TopToolBarArea, toolBar)支持 Top/Bottom/Left/Right 四个方向限制停靠范围toolBar-setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea)核心属性setFloatable(bool)是否允许浮动默认 true浮动时可拖拽为独立窗口setMovable(bool)是否允许移动默认 true关闭后无法调整停靠位置addAction(action)添加菜单项复用菜单栏的 QAction保持功能一致addWidget(widget)添加自定义控件如按钮、输入框分割线addSeparator()用于区分不同功能组。3.1 实战示例1创建工具栏(基本使用)#include mainwindow.h #include ui_mainwindow.h #include QToolBar #include QDebug MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); // 创建菜单栏 QMenuBar* menuBar this-menuBar(); this-setMenuBar(menuBar); // 创建菜单 QMenu* menu new QMenu(文件); menuBar-addMenu(menu); // 工具栏需要自己手动创建自身不会自动创建 QToolBar* toolBar new QToolBar(); this-addToolBar(toolBar); // 创建菜单项 QAction* action1 new QAction(保存); QAction* action2 new QAction(打开); action1-setToolTip(点击这里保存文件); action1-setIcon(QIcon(:/save.png)); action2-setIcon(QIcon(:/open.png)); // 菜单项还可以放到菜单中 menu-addAction(action1); menu-addAction(action2); // 菜单项放到工具栏中 toolBar-addAction(action1); toolBar-addAction(action2); connect(action1,QAction::triggered,this,MainWindow::handle1); connect(action2,QAction::triggered,this,MainWindow::handle2); } MainWindow::~MainWindow() { delete ui; } void MainWindow::handle1() { qDebug()handle1; } void MainWindow::handle2() { qDebug()handle2; }关键注意点菜单项QAction可复用同时添加到菜单栏和工具栏无需重复创建3.2 实战示例2多个工具栏的使用#include mainwindow.h #include ui_mainwindow.h #include QToolBar MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); QToolBar* toolBar1 new QToolBar(); QToolBar* toolBar2 new QToolBar(); this-addToolBar(toolBar1); this-addToolBar(Qt::LeftToolBarArea,toolBar2); // 只允许停靠左侧或者右侧 toolBar2-setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); // 设置不允许浮动 toolBar2-setFloatable(false); // 设置不允许移动 toolBar2-setMovable(false); QAction* action1 new QAction(动作1); QAction* action2 new QAction(动作2); QAction* action3 new QAction(动作3); QAction* action4 new QAction(动作4); toolBar1-addAction(action1); toolBar1-addAction(action2); toolBar2-addAction(action3); toolBar2-addAction(action4); } MainWindow::~MainWindow() { delete ui; }关键注意点setMovable(false)会关闭移动功能此时setAllowedAreas()也会失效需谨慎使用自定义控件如按钮、输入框通过addWidget()添加扩展工具栏功能如搜索、筛选多个工具栏会按添加顺序排列可通过拖拽调整顺序默认允许移动时四. 状态栏Status Bar状态信息展示区域状态栏位于窗口底部用于显示三类信息实时消息如 “已保存”、永久消息如版本号、进度提示如文件加载进度。Qt 中通过QStatusBar类实现支持添加标签、进度条等控件全局唯一。核心属性与 API创建方法statusBar()QMainWindow 内置方法直接获取状态栏对象信息显示实时消息showMessage(消息内容, 3000)3000 为显示时长单位 ms0 表示永久显示永久消息addWidget(label)左侧添加、addPermanentWidget(label)右侧添加不会被实时消息覆盖核心功能clearMessage()清空实时消息、setSizeGripEnabled(false)关闭右下角大小调整 grip。4.1 实战示例多功能状态栏实时消息 文本 进度条 按钮#include mainwindow.h #include ui_mainwindow.h #include QLabel #include QProgressBar #include QPushButton MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); // 存在就获取不存在就创建 QStatusBar* statusBar this-statusBar(); // 如果状态栏没有被创建这样的设置是必要的 // 如果状态栏已经在窗口中存在这样的设置意义不大但也没副作用 this-setStatusBar(statusBar); // 显示一个临时的信息 // statusBar-showMessage(这是一个状态消息,3000); // 3000ms 后消失 // 给状态栏中添加一个子控件 QLabel* label new QLabel(这是一个QLabel); statusBar-addWidget(label); // QLabel* label2 new QLabel(这是另一个QLabel); // statusBar-addWidget(label2,2); // 2拉伸系数 QProgressBar* progressBar new QProgressBar(); progressBar-setRange(0,100); progressBar-setValue(50); statusBar-addWidget(progressBar); QPushButton* button new QPushButton(按钮); statusBar-addPermanentWidget(button); } MainWindow::~MainWindow() { delete ui; }关键注意点状态栏全局唯一addPermanentWidget()添加的控件会固定在右侧不会被showMessage()的实时消息覆盖进度条等动态控件默认隐藏需要时显示避免占用状态栏空间实时消息的显示时长单位为毫秒ms0 表示永久显示需手动调用clearMessage()清空状态栏高度默认固定添加的控件需注意尺寸避免超出状态栏范围。五. 浮动窗口Dock Widget辅助功能承载区域浮动窗口铆接部件是可浮动、可停靠的辅助窗口通常位于中心部件周围用于承载辅助功能如日志输出、属性设置、文件列表。它支持拖拽停靠到窗口边缘或浮动为独立窗口Qt 中通过QDockWidget类实现可多个共存。核心属性与 API创建方法new QDockWidget(浮动窗口名称, this)通过addDockWidget()添加到窗口停靠位置addDockWidget(Qt::RightDockWidgetArea, dockWidget)支持 Top/Bottom/Left/Right 四个方向限制停靠范围setAllowedAreas(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea)核心属性setFloating(false)是否默认浮动默认 truefalse 为停靠状态setWidget(widget)设置浮动窗口的内部控件如列表、文本框setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable)设置支持的功能移动、关闭、浮动核心信号topLevelChanged(bool)浮动 / 停靠状态切换时触发。5.1 实战示例浮动窗口的基本使用#include mainwindow.h #include ui_mainwindow.h #include QDockWidget #include QLabel #include QPushButton #include QVBoxLayout MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); // 给主窗口添加一个子窗口 QDockWidget* dockWidget new QDockWidget(); // 使用 addDockWidget 方法吧浮动窗口添加到子窗口中 this-addDockWidget(Qt::LeftDockWidgetArea,dockWidget); // 给浮动窗口设置标题 dockWidget-setWindowTitle(这是一个浮动窗口); // 给浮动窗口内部添加一些其他控件 // 不能直接给这个浮动窗口添加子控件而是需要创建一些单独的 QWidget 把要添加的控件加入到 QWidget // 然后把 QWidget 设置到 dockWidget QWidget* container new QWidget(); dockWidget-setWidget(container); // 创建布局管理器把布局管理器设置到 QWidget QVBoxLayout* layout new QVBoxLayout(); container-setLayout(layout); // 创建其他控件 QLabel* label new QLabel(这是一个QLabel); QPushButton* button new QPushButton(这是按钮); layout-addWidget(label); layout-addWidget(button); // 设置浮动窗口允许停靠的位置 dockWidget-setAllowedAreas(Qt::LeftDockWidgetArea | Qt::TopDockWidgetArea); } MainWindow::~MainWindow() { delete ui; }六. 核心组件避坑指南菜单栏新建项目时必须选择QMainWindow作为基类否则无法使用menuBar()等内置方法QAction的快捷键需使用QKeySequence类避免自定义字符串导致快捷键失效。工具栏禁止移动setMovable(false)后停靠位置也无法调整需根据需求谨慎设置自定义控件尺寸不宜过大避免工具栏占用过多窗口空间。状态栏addPermanentWidget()添加的控件在右侧不会被实时消息覆盖适合放置版本号等永久信息进度条等动态控件需默认隐藏progressBar-hide();// 默认隐藏需要时显示使用时再显示避免状态栏杂乱。浮动窗口必须通过setWidget()设置内部控件否则浮动窗口无法正常显示限制停靠范围时需确保setMovable(true)否则限制无效。
延伸阅读

更多相关文章

2026/9/30 7:16:45

【2018-05-04】Lightweight M2M简单介绍

[历史归档] 本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。 发布时间: 2018-05-04 | 标题:Lightweight M2M简单介绍 | 分类: 编程 | 标签: c…

2026/9/30 7:16:45

小白程序员快速入门:Agent大模型应用的核心流程解析

文章指出,大模型(LLM)竞争力关键在于流程设计而非模型参数。介绍三种核心Agent机制:ReAct(思维链驱动的推理行动)、Plan-and-Execute(规划执行模式)及Reflexion(自我反思…

2026/9/30 7:16:45

【2018-04-04】TLS简单笔记-几种常用加密算法比较

[历史归档] 本文原发布于 cstriker1407.info 个人博客,内容为历史存档,仅供参考。 发布时间: 2018-04-04 | 标题:TLS简单笔记-几种常用加密算法比较 | 分类: 编程 | 标签&…

2026/9/30 8:06:48

通达OA二次开发实战:从环境配置到模块开发全解析

简介:《通达OA二次开发手册》是一份面向具备编程基础的技术人员的Office Anywhere网络智能办公系统定制化开发指南,旨在帮助读者厘清系统架构、掌握扩展开发的关键路径。手册以2015年发布的V8.1版本为例,系统讲解开发环境配置、FastCGI进程管…

2026/9/30 8:06:48

JSP女性交流网站源码:从环境配置到核心功能排查

做计算机毕设的同学,十个里有三四个会在选题表上看到"XX交流网站"这类题目,而"女性交流网站"又是其中出现频率相当高的一类。原因不复杂:业务场景好理解,功能模块足够撑起一份毕设的工作量,答辩老…

2026/9/30 8:06:48

MySQL DATE_FORMAT函数全解析:格式符、陷阱与性能优化

1. 为什么一个日期格式化函数值得单独写一篇 先说一个我真实经历过的场景。凌晨两点被电话叫醒,说线上商城的充值记录时间全乱了,用户看到的支付时间比实际时间晚了整整两天。查了半天,问题出在一条 SQL 上:有人为了把时间转成“2…

2026/9/30 8:06:48

鸿蒙平台下Flutter开源合规审计:license_checker适配实践

1. 项目背景与核心痛点1.1 license_checker 在开源合规审计里的价值先把结论放在前面:License 审计这事,在鸿蒙生态里比在安卓时代更麻烦,也更躲不掉。一个 Flutter 应用跑起来之后,背后到底依赖了多少个开源项目?如果…

2026/9/30 8:06:48

Anaconda虚拟环境底层原理与PyCharm配置真相

1. 为什么你每次在PyCharm里跑代码都报“ModuleNotFoundError”,而同事的项目却稳如泰山? 我见过太多人把Python开发环境搞成“玄学现场”:明明pip install了requests,运行时却提示找不到;换台电脑重装一遍&#xff0c…

2026/9/30 8:01:48

科研绘图效率利器:从素材库到Cell级论文配图的完整指南

上周刚帮实验室一个师弟改完机制图,他把线粒体画成了椭圆加波浪线,细胞核用矩形加几个点,流速箭头大小完全不统一,一眼看上去像三种风格硬拼在一起。我花了两个小时把它们全部替换成BioRender的标准图标,整套图立刻就不…

2026/9/29 11:07:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 7:00:49

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 0:01:22

MATLAB+Yalmip+CPLEX实战:综合能源系统优化调度全流程解析

做综合能源系统优化调度这活儿,最痛苦的不是建模本身,而是模型写完之后不知道该怎么求解。看论文里轻飘飘一句“采用Yalmip调用CPLEX求解”,自己上手时却往往卡在环境配置、变量声明、约束写法和求解状态判读上,一耗就是两三天。这…

2026/9/30 0:01:22

I3C比I2C快10倍?RK3576实战:速率、DTS配置与混合总线避坑指南

I3C 比 I2C 快 10 倍?这句话在嵌入式群里传了很久,每次都能吵出一堆截图。前段时间我正好在 RK3576 上调板级 I3C 接口,从控制器寄存器一路摸到 Linux DTS 配置,踩了不少坑,也把这笔速度账彻底算明白了。本文就用 RK35…

2026/9/30 0:01:22

字符串转对象:JSON.parse、new Function与URLSearchParams

“字符串转对象”这几个字,我在技术群里见过的问法至少有十几种:有人拿着一串{a:1,b:2}说 JSON.parse 直接报错,有人要从 URL 里抠出参数,还有人只是想把abc变成能挂属性的东西。js 这门语言里,字符串和对象之间的转换…

2026/9/29 3:53:39

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/29 9:46:12

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/29 6:36:14

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑