Qt 主窗口开发三件套:菜单栏、工具栏、状态栏与停靠窗口实战

Qt 主窗口开发三件套:菜单栏、工具栏、状态栏与停靠窗口实战 Qt 主窗口开发三件套菜单栏、工具栏、状态栏与停靠窗口实战Qt 主窗口开发三件套菜单栏、工具栏、状态栏与停靠窗口实战前言1. 为什么 Qt 很适合做传统桌面程序2. QMenuBar菜单栏是主窗口的骨架2.1 给菜单设置快捷方式2.2 给action(动作)设置快捷方式2.3 设置子菜单2.4 在菜单中给每个菜单项添加分隔线3. QAction菜单项和工具栏按钮的共同抽象4. QToolBar把高频操作提到最前面5. QStatusBar轻量反馈特别好用6. QDockWidget让界面更像 IDE7. 这几块组件之间怎么协作8. 一个简化版主窗口思路9. 我在这组练习里的体会9.1 主窗口不是“多几个控件”而是结构升级9.2 QAction 这个抽象特别值钱9.3 桌面程序的味道很多时候就来自这些细节10. 总结Qt 主窗口开发三件套菜单栏、工具栏、状态栏与停靠窗口实战前言很多人第一次接触 Qt最先看到的是按钮、标签、输入框这些基础控件。但如果真的想做一个“像样的桌面程序”光会摆控件还不够真正能把桌面软件气质拉起来的其实是主窗口这一整套东西。比如顶部的菜单栏常用操作放到工具栏底部的状态栏可以拖来拖去的停靠窗口这些东西组合起来才会让一个程序看起来像编辑器、像管理工具、像真正的桌面应用。我这篇文章就结合自己的一些经验把 Qt 主窗口里最常用的几块讲清楚。1. 为什么 Qt 很适合做传统桌面程序Qt 有一个很明显的特点它对桌面程序那种“菜单 工具栏 状态栏 子面板”的结构支持得特别完整。如果你只是做一个很小的弹窗程序这些能力不一定重要。但如果你想做配置工具文件管理器数据录入界面IDE 风格的小工具那主窗口体系就会很有价值。在 Qt 里这些能力大多都围绕QMainWindow展开。相比普通的QWidgetQMainWindow天生就更适合承载复杂界面。2. QMenuBar菜单栏是主窗口的骨架菜单栏通常是主窗口最显眼的结构之一像一些主流的IDE比如VScode都会有自己的菜单栏在 Qt 里我们可以先拿到主窗口自己的菜单栏再往里面加菜单QMenuBar*menubarthis-menuBar();this-setMenuBar(menubar);QMenu*menunewQMenu(文件);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*action1newQAction(保存);QAction*action2newQAction(打开);这两个动作既可以加进菜单menu-addAction(action1);menu-addAction(action2);也可以加进工具栏toolbar-addAction(action1);toolbar-addAction(action2);这就是 Qt 很优雅的一点菜单和工具栏虽然长得不一样但背后操作的其实是同一个动作对象这相当于一个功能在不同的地方的复用可以节省资源。这样做的好处是逻辑统一状态统一不容易重复写代码4. QToolBar把高频操作提到最前面菜单适合分组工具栏适合高频操作。比如保存、打开、刷新这些动作如果每次都要走菜单效率会低很多。放到工具栏上用户一眼就能点到。我现在这个QToolBar示例里核心结构就是QToolBar*toolbarnewQToolBar();this-addToolBar(toolbar);QAction*action1newQAction(保存);QAction*action2newQAction(打开);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*statusbarthis-statusBar();this-setStatusBar(statusbar);然后可以往里加控件QLabel*labelnewQLabel(这是一个label);statusbar-addWidget(label);QProgressBar*progressbarnewQProgressBar();progressbar-setRange(0,100);progressbar-setValue(50);statusbar-addWidget(progressbar);我自己挺喜欢状态栏的原因是它非常适合放“轻提示”。比起每次都弹对话框状态栏的反馈更轻不打断用户流程能让用户的体验很好。运行结果6. QDockWidget让界面更像 IDE如果说菜单栏、工具栏、状态栏已经能让程序像个桌面软件了那QDockWidget会让它更像一个“专业桌面工具”。它最大的特点是可以作为可停靠、可拖动的子面板存在。比如QDockWidget*docknewQDockWidget();this-addDockWidget(Qt::LeftDockWidgetArea,dock);// 设置初始的停靠区域QWidget*widgetnewQWidget();dock-setWidget(widget);再往里面放布局和控件QVBoxLayout*vboxnewQVBoxLayout();widget-setLayout(vbox);QPushButton*button1newQPushButton(按钮1);QPushButton*button2newQPushButton(按钮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 类”而是我开始理解一个桌面程序的界面不只是控件堆出来的更是结构设计出来的。