Qt 主窗口开发三件套:菜单栏、工具栏、状态栏与停靠窗口实战
- Qt 主窗口开发三件套:菜单栏、工具栏、状态栏与停靠窗口实战
- 前言
- 1. 为什么 Qt 很适合做传统桌面程序
- 2. QMenuBar:菜单栏是主窗口的骨架
- 2.1 给菜单设置快捷方式
- 2.2 给action(动作)设置快捷方式
- 2.3 设置子菜单
- 2.4 在菜单中给每个菜单项添加分隔线
- 3. QAction:菜单项和工具栏按钮的共同抽象
- 4. QToolBar:把高频操作提到最前面
- 5. QStatusBar:轻量反馈特别好用
- 6. QDockWidget:让界面更像 IDE
- 7. 这几块组件之间怎么协作
- 8. 一个简化版主窗口思路
- 9. 我在这组练习里的体会
- 9.1 主窗口不是“多几个控件”,而是结构升级
- 9.2 QAction 这个抽象特别值钱
- 9.3 桌面程序的味道,很多时候就来自这些细节
- 10. 总结
Qt 主窗口开发三件套:菜单栏、工具栏、状态栏与停靠窗口实战
前言
很多人第一次接触 Qt,最先看到的是按钮、标签、输入框这些基础控件。但如果真的想做一个“像样的桌面程序”,光会摆控件还不够,真正能把桌面软件气质拉起来的,其实是主窗口这一整套东西。
比如:
- 顶部的菜单栏
- 常用操作放到工具栏
- 底部的状态栏
- 可以拖来拖去的停靠窗口
这些东西组合起来,才会让一个程序看起来像编辑器、像管理工具、像真正的桌面应用。
我这篇文章,就结合自己的一些经验,把 Qt 主窗口里最常用的几块讲清楚。
1. 为什么 Qt 很适合做传统桌面程序
Qt 有一个很明显的特点:它对桌面程序那种“菜单 + 工具栏 + 状态栏 + 子面板”的结构支持得特别完整。
如果你只是做一个很小的弹窗程序,这些能力不一定重要。
但如果你想做:
- 配置工具
- 文件管理器
- 数据录入界面
- IDE 风格的小工具
那主窗口体系就会很有价值。
在 Qt 里,这些能力大多都围绕QMainWindow展开。相比普通的QWidget,QMainWindow天生就更适合承载复杂界面。
2. QMenuBar:菜单栏是主窗口的骨架
菜单栏通常是主窗口最显眼的结构之一,像一些主流的IDE,比如VScode都会有自己的菜单栏:
在 Qt 里,我们可以先拿到主窗口自己的菜单栏,再往里面加菜单:
QMenuBar*menubar=this->menuBar();this->setMenuBar(menubar);QMenu*menu=newQMenu("文件");menubar->addMenu(menu);这一步其实在做两件事:
- 建立主窗口最上方的菜单容器
- 把功能按“文件、编辑、视图”这种思路组织起来
我自己练这组例子的时候,一个很明显的感受是:
菜单栏不是为了好看,而是为了把功能分组。
如果一个程序功能一多,没有菜单栏的话,用户会很快找不到入口。
运行结果:
2.1 给菜单设置快捷方式
菜单栏是必须有菜单的,否则就没有意义。
但是有时候我们希望给有一些高频使用的菜单,比如文件,设置快捷方式,Qt中支持下面的方式:
// 创建菜单 QMenu* menu1 = new QMenu("文件 (&F)"); QMenu* menu2 = new QMenu("编辑 (&E)"); QMenu* menu3 = new QMenu("构建 (&B)");&F就是将对应的菜单和大写字母绑定在了一起,当我们按那个大写字母时,等同于按下了那个菜单键。
2.2 给action(动作)设置快捷方式
我们不仅可以给菜单设置快捷方式,还可以给动作设置:
QAction* action1 = new QAction("打开 (&A)"); QAction* action2 = new QAction("关闭 (&C)"); QAction* action3 = new QAction("查看 (&G)");运行结果:
我们先按快捷方式F打开菜单文件,再按快捷方式A就能触发action1的动作。
2.3 设置子菜单
在Qt中也支持给某一个菜单设置子菜单:
QMenuBar* menuBar = new QMenuBar(); this->setMenuBar(menuBar); QMenu* menuParent = new QMenu("父菜单"); QMenu* menuChild = new QMenu("子菜单"); menuBar->addMenu(menuParent); menuParent->addMenu(menuChild);运行结果:
2.4 在菜单中给每个菜单项添加分隔线
有时候,某个菜单的菜单项太多了,用来把一组菜单项和另一组菜单项视觉上隔开,让菜单结构更清晰。
menu->addSeparator()运行结果:
3. QAction:菜单项和工具栏按钮的共同抽象
Qt 里有个特别值得注意的类,叫QAction。
你可以把它理解成“一个动作”,而不是“一个按钮”。
例如:
QAction*action1=newQAction("保存");QAction*action2=newQAction("打开");这两个动作既可以加进菜单:
menu->addAction(action1);menu->addAction(action2);也可以加进工具栏:
toolbar->addAction(action1);toolbar->addAction(action2);这就是 Qt 很优雅的一点:
菜单和工具栏虽然长得不一样,但背后操作的其实是同一个动作对象,这相当于一个功能在不同的地方的复用,可以节省资源。
这样做的好处是:
- 逻辑统一
- 状态统一
- 不容易重复写代码
4. QToolBar:把高频操作提到最前面
菜单适合分组,工具栏适合高频操作。
比如保存、打开、刷新,这些动作如果每次都要走菜单,效率会低很多。放到工具栏上,用户一眼就能点到。
我现在这个QToolBar示例里,核心结构就是:
QToolBar*toolbar=newQToolBar();this->addToolBar(toolbar);QAction*action1=newQAction("保存");QAction*action2=newQAction("打开");action1->setIcon(QIcon(":/save.png"));action2->setIcon(QIcon(":/open.png"));toolbar->addAction(action1);toolbar->addAction(action2);然后再把动作连到槽函数:
connect(action1,&QAction::triggered,this,&MainWindow::handle1);connect(action2,&QAction::triggered,this,&MainWindow::handle2);这一步特别适合写进博客,因为它能很清楚地体现:
QAction是行为QToolBar是行为的可视化载体- 图标和 tooltip 则是在帮用户快速识别行为,可以给动作添加图标属性,便于用户辨别。
运行结果:
5. QStatusBar:轻量反馈特别好用
状态栏很容易被忽略,但它其实是桌面应用里特别实用的一块。
比如:
- 提示“保存成功”
- 展示当前状态
- 放一个进度条
- 放一些小标签
在 Qt 里拿到状态栏非常直接:
QStatusBar*statusbar=this->statusBar();this->setStatusBar(statusbar);然后可以往里加控件:
QLabel*label=newQLabel("这是一个label");statusbar->addWidget(label);QProgressBar*progressbar=newQProgressBar();progressbar->setRange(0,100);progressbar->setValue(50);statusbar->addWidget(progressbar);我自己挺喜欢状态栏的原因是,它非常适合放“轻提示”。
比起每次都弹对话框,状态栏的反馈更轻,不打断用户流程,能让用户的体验很好。
运行结果:
6. QDockWidget:让界面更像 IDE
如果说菜单栏、工具栏、状态栏已经能让程序像个桌面软件了,那QDockWidget会让它更像一个“专业桌面工具”。
它最大的特点是:
可以作为可停靠、可拖动的子面板存在。
比如:
QDockWidget*dock=newQDockWidget();this->addDockWidget(Qt::LeftDockWidgetArea,dock);// 设置初始的停靠区域QWidget*widget=newQWidget();dock->setWidget(widget);再往里面放布局和控件:
QVBoxLayout*vbox=newQVBoxLayout();widget->setLayout(vbox);QPushButton*button1=newQPushButton("按钮1");QPushButton*button2=newQPushButton("按钮2");vbox->addWidget(button1);vbox->addWidget(button2);这时候你就已经有一个“可挂载的边栏面板”了。
它特别适合做:
- 工具面板
- 属性面板
- 日志窗口
- 辅助导航区域
很多编辑器类软件之所以看起来很专业,很大一部分原因就是它们把主界面拆成了主工作区 + 若干停靠面板。
运行结果:
还可以设置允许停靠的区域:
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::TopDockWidgetArea);7. 这几块组件之间怎么协作
当我把这些小工程连起来看时,我越来越觉得 Qt 主窗口的设计非常像一套分工明确的体系:
QMenuBar:负责分类入口QAction:负责动作抽象QToolBar:负责高频快捷入口QStatusBar:负责轻量反馈QDockWidget:负责附属工作区
你会发现,它们并不是孤立的控件,而更像一个“桌面程序骨架”。
如果你的程序只是单页面按钮堆砌,用户会觉得它像个 demo。
但一旦这几块配合起来,程序的完成度和专业感会明显提高。
8. 一个简化版主窗口思路
如果让我用现在这些练习工程拼一个小型桌面工具,我会这样组织:
- 顶部菜单栏:文件、编辑、视图、帮助
- 工具栏:保存、打开、刷新
- 中间主区域:实际业务界面
- 左边停靠窗口:导航或工具面板
- 底部状态栏:显示提示和进度
这样其实已经很像一个真正的桌面应用框架了。
哪怕业务逻辑还不复杂,界面结构先搭对,后面扩展起来也会顺很多。
9. 我在这组练习里的体会
9.1 主窗口不是“多几个控件”,而是结构升级
普通控件更多是在填充内容,主窗口组件更像是在组织内容。
它们决定的是“界面怎么分层、功能怎么分组、反馈怎么展示”。
9.2 QAction 这个抽象特别值钱
我一开始并没有很重视QAction,后来才发现它是把菜单和工具栏统一起来的关键。
这也是 Qt 设计里我挺喜欢的一点:它不是把 UI 元素硬堆在一起,而是先抽象动作,再决定动作怎么显示。
9.3 桌面程序的味道,很多时候就来自这些细节
一个工具栏图标、一个状态栏提示、一个可停靠面板,单独看都不算大功能。
但它们放在一起,用户就会感觉这个程序更像“产品”,而不只是“练习工程”。
10. 总结
如果把 Qt 主窗口最核心的几块抽出来,我觉得可以记成一句话:
菜单栏负责分组,工具栏负责快捷,状态栏负责反馈,停靠窗口负责扩展。
这四块一旦配合起来,QMainWindow的价值就出来了。
而且它们都不是只适合大项目。哪怕你现在只是做课程练习,只要有意识地把这些结构练熟,后面真写稍微复杂一点的桌面工具时,就会轻松很多。
对我来说,这组练习最大的收获不是“我会用了几个 Qt 类”,而是我开始理解:
一个桌面程序的界面,不只是控件堆出来的,更是结构设计出来的。