Qt 主窗口核心组件实战:菜单栏、工具栏、状态栏、浮动窗口全攻略


🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:


文章目录

  • 前言:
  • [一. QMainWindow 组件布局概览](#一. QMainWindow 组件布局概览)
  • [二. 菜单栏(Menu Bar):核心功能分类入口](#二. 菜单栏(Menu Bar):核心功能分类入口)
    • [2.1 实战示例1:菜单栏 && 菜单 && 菜单项的基本使用](#2.1 实战示例1:菜单栏 && 菜单 && 菜单项的基本使用)
    • [2.2 实战示例2:添加快捷键](#2.2 实战示例2:添加快捷键)
    • [2.3 实战示例3:添加子菜单](#2.3 实战示例3:添加子菜单)
    • [2.4 实战示例4:添加分割线和图标](#2.4 实战示例4:添加分割线和图标)
  • [三. 工具栏(Tool Bar):常用功能快捷入口](#三. 工具栏(Tool Bar):常用功能快捷入口)
    • [3.1 实战示例1:创建工具栏(基本使用)](#3.1 实战示例1:创建工具栏(基本使用))
    • [3.2 实战示例2:多个工具栏的使用](#3.2 实战示例2:多个工具栏的使用)
  • [四. 状态栏(Status Bar):状态信息展示区域](#四. 状态栏(Status Bar):状态信息展示区域)
    • [4.1 实战示例:多功能状态栏(实时消息 + 文本 + 进度条 + 按钮)](#4.1 实战示例:多功能状态栏(实时消息 + 文本 + 进度条 + 按钮))
  • [五. 浮动窗口(Dock Widget):辅助功能承载区域](#五. 浮动窗口(Dock Widget):辅助功能承载区域)
    • [5.1 实战示例:浮动窗口的基本使用](#5.1 实战示例:浮动窗口的基本使用)
  • [六. 核心组件避坑指南](#六. 核心组件避坑指南)
  • 结语:

前言:

Qt 的 QMainWindow 是构建桌面应用主窗口的核心类,它内置了一套标准化布局,包含菜单栏、工具栏、状态栏、浮动窗口(铆接部件)和中心部件五大核心组件。这些组件各司其职,共同构成了专业桌面应用的基础框架 ------ 菜单栏负责核心功能分类,工具栏提供快捷操作,状态栏显示状态信息,浮动窗口承载辅助功能,中心部件作为核心交互区域。本文逐一拆解 QMainWindow 四大核心组件(菜单栏、工具栏、状态栏、浮动窗口)的属性、创建方法和实战场景,通过可直接运行的代码示例,帮你快速掌握 Qt 主窗口的搭建技巧,轻松打造标准化桌面应用界面。


一. QMainWindow 组件布局概览

在开始实战前,先明确 QMainWindow 各组件的默认布局位置,避免后续开发中组件位置混乱:

  • 菜单栏(Menu Bar):顶部标题栏下方,全局唯一,用于分类核心功能(如文件、编辑、帮助);
  • 工具栏(Tool Bar):菜单栏下方或两侧,可多个共存,用于常用功能的快捷访问;
  • 中心部件(Central Widget):窗口核心区域,占比最大,用于放置核心交互控件(如文本编辑、表格);
  • 浮动窗口(Dock Widget):中心部件周围,可浮动可停靠,用于辅助功能(如日志、属性设置);
  • 状态栏(Status Bar):窗口底部,全局唯一,用于显示实时状态、永久信息或进度提示。

所有组件均需依托 QMainWindow 作为父类,因此新建项目时需选择 QMainWindow 作为基类(而非 QWidget)。



二. 菜单栏(Menu Bar):核心功能分类入口

菜单栏是桌面应用的 "功能导航栏" ,通过层级结构(菜单栏 --> 菜单 --> 菜单项)组织核心功能,支持快捷键,分割线,是用户操作的主要入口。Qt 中通过 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("Ctrl+S"))(设置快捷键)(还有别的方法看下面示例);
  • 核心信号QAction::triggered()(菜单项被点击时触发)。

2.1 实战示例1:菜单栏 && 菜单 && 菜单项的基本使用

cpp 复制代码
#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 = this->menuBar();
    // 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.2 实战示例2:添加快捷键

cpp 复制代码
#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);

    // 创建四个菜单项
    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";
}
  • 关键注意点:
    • 菜单项 QAction 可复用(同时添加到菜单栏和工具栏),无需重复创建(后续会体现);
    • &X 格式的菜单名称用于设置 Alt+X 快捷键(如 &F 对应 Alt+F 打开文件菜单);

2.3 实战示例3:添加子菜单

cpp 复制代码
#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* parentMenu = new QMenu("父菜单");
    QMenu* childMenu1 = new QMenu("子菜单1");
    QMenu* childMenu2 = new QMenu("子菜单2");
    menuBar->addMenu(parentMenu);
    parentMenu->addMenu(childMenu1);
    parentMenu->addMenu(childMenu2);

    QAction* action1 = new QAction("菜单项1");
    QAction* action2 = new QAction("菜单项2");
    childMenu1->addAction(action1);
    childMenu1->addAction(action2);
}

MainWindow::~MainWindow()
{
    delete ui;
}


2.4 实战示例4:添加分割线和图标

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // QMenuBar* menuBar = new QMenuBar();
    QMenuBar* menuBar = this->menuBar(); // 更标准的写法,防止内存泄露
    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->addSeparator();
    menu->addAction(action2);
}

MainWindow::~MainWindow()
{
    delete ui;
}
  • 关键注意点 :分割线 addSeparator() 用于区分不同功能组(如 "保存" 和 "退出" 之间),提升可读性。

三. 工具栏(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:创建工具栏(基本使用)

cpp 复制代码
#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"));

    // 菜单项设置到工具栏
    toolBar->addAction(action1);
    toolBar->addAction(action2);
    // 菜单项设置到菜单
    menu->addAction(action1);
    menu->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:多个工具栏的使用

cpp 复制代码
#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 为显示时长,单位 ms,0 表示永久显示);
    • 永久消息:addWidget(label)(左侧添加)、addPermanentWidget(label)(右侧添加,不会被实时消息覆盖);
  • 核心功能clearMessage()(清空实时消息)、setSizeGripEnabled(false)(关闭右下角大小调整 grip)。

4.1 实战示例:多功能状态栏(实时消息 + 文本 + 进度条 + 按钮)

cpp 复制代码
#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);

    // 放置一些控件
    QLabel* label = new QLabel("这是一个Label");
    statusBar->addWidget(label); // 从左往右添加
    QProgressBar* progressBar = new QProgressBar();
    progressBar->setRange(0, 100);
    progressBar->setValue(50);
    statusBar->addWidget(progressBar);
    QPushButton* pushButton = new QPushButton("按钮");
    statusBar->addPermanentWidget(pushButton); // 从右往左添加
}

MainWindow::~MainWindow()
{
    delete ui;
}
  • 关键注意点:
    • 状态栏全局唯一,addPermanentWidget() 添加的控件会固定在右侧,不会被 showMessage() 的实时消息覆盖;
    • 进度条等动态控件默认隐藏,需要时显示,避免占用状态栏空间;
    • 实时消息的显示时长单位为毫秒(ms),0 表示永久显示,需手动调用 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):是否默认浮动(默认 true,false 为停靠状态);
    • setWidget(widget):设置浮动窗口的内部控件(如列表、文本框);
    • setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable):设置支持的功能(移动、关闭、浮动);
  • 核心信号topLevelChanged(bool)(浮动 / 停靠状态切换时触发)。

5.1 实战示例:浮动窗口的基本使用

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDockWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 给主窗口添加一个子窗口
    QDockWidget* dockWidget = new QDockWidget();
    this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);

    // 浮动窗口也是可以设置标题的
    dockWidget->setWindowTitle("这是浮动窗口");

    // 给浮动窗口内部添加一些其他的控件
    // 不能直接给这个浮动窗口添加子控件,而是需要创建出一个单独的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),否则限制无效。

结语:

html 复制代码
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!

结语:本文完整覆盖了 Qt 主窗口四大核心组件的实战用法,从单独组件创建到综合应用整合,所有代码均可直接运行。这些组件是 Qt 桌面应用的基础,掌握后可快速搭建标准化、专业化的主窗口界面,适配记事本、编辑器、管理工具等各类桌面应用场景。

✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど

相关推荐
大刚测试开发实战5 小时前
TestHub V0.2.2版本发布,附更新指南
人工智能
冬奇Lab6 小时前
Agent 系列(21):Harness 测试工程——45 个测试怎么设计,以及它发现了什么 bug
人工智能·llm·agent
冬奇Lab6 小时前
每日一个开源项目(第133篇):EchoBird - 把 AI 工具的安装和部署做成傻瓜操作
人工智能·开源·资讯
程序员龙叔7 小时前
编写高质量 Skill 系列 -- 如何设计需求分析与用例生成的 SKILL
自动化测试·软件测试·python·软件测试工程师·接口测试·性能测试·skill·ai测试
IT_陈寒8 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
用户5191495848459 小时前
Windows 渗透测试载荷加载器 POC 工具集
人工智能·aigc
大树889 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
用户8356290780519 小时前
使用 Python 操作 Word 内容控件
后端·python
摇滚侠9 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
LDR0069 小时前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言