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 桌面应用的基础,掌握后可快速搭建标准化、专业化的主窗口界面,适配记事本、编辑器、管理工具等各类桌面应用场景。

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

相关推荐
愚公搬代码7 小时前
【愚公系列】《AI短视频创作一本通》019-AI语音及音乐的创作(AI短视频语音创作实例)
人工智能·音视频
RisunJan7 小时前
Linux命令-lprm(删除打印队列中任务)
linux·运维·服务器
Ronin3057 小时前
持久化数据管理中心模块
开发语言·c++·rabbitmq·gtest
wukangjupingbb7 小时前
AI在靶点识别(Target Identification)中的关键作用与开源工具生态
人工智能·开源
Web极客码7 小时前
WordPress从经典编辑器升级到古腾堡编辑器
运维·编辑器·wordpress
froginwe117 小时前
AJAX 实例详解
开发语言
魔力军7 小时前
Rust学习Day2: 变量与可变性、数据类型和函数和控制流
开发语言·学习·rust
power 雀儿7 小时前
FFN前馈网络C++实现
人工智能·深度学习
多恩Stone7 小时前
【3D AICG 系列-8】PartUV 流程图详解
人工智能·算法·3d·aigc·流程图