Qt MainWindow:主窗口组件的介绍与正确使用
文章目录
一、QMainWindow
QMainWindow 是⼀个为用户提供主窗⼝程序的类,继承⾃ QWidget 类,并且提供了⼀个预定义的
布局。QMainWindow 包含 ⼀个菜单栏(menu bar)、多个⼯具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个 中⼼部件(central widget),它内置了标准化的界面结构,无需手动拼接布局,直接适配桌面程序的通用交互逻辑,整体布局分为 6 个核心区域:
┌─────────────────────────────────────────────┐
│ 标题栏(Window Title)- 系统自带/Qt 封装 │
├─────────────────────────────────────────────┤
│ 菜单栏(Menu Bar)- 顶部固定,文本化功能入口 │
├─────────────────────────────────────────────┤
│ 工具栏(Tool Bar)- 菜单栏下,可拖拽快捷按钮 │
├───────────────┬─────────────────────────────┤
│ 停靠窗口 │ │
│(Dock Widget) │ 中心部件(Central Widget) │
│ (侧边面板) │ (窗口核心内容区,必须设置) │
├───────────────┴─────────────────────────────┤
│ 状态栏(Status Bar)- 底部固定,显示状态信息 │
└─────────────────────────────────────────────┘
在勾选UI文件创建MainWindow时,QMainWindow必须且自动生成:
centralWidget(中心窗口):QMainWindow的核心区域,用于承载主要内容;menuBar(菜单栏):窗口顶部的默认菜单栏;statusBar(状态栏):窗口底部的默认状态栏。
这三个组件在 QMainWindow 中只能有一个,无法创建多个,且会直接出现在MainWindow.ui的可视化界面中,同时在编译生成的ui_MainWindow.h里自动生成对应的指针(如ui->centralWidget、ui->menuBar、ui->statusBar)。
二、组件详解
1. 标题栏(Window Title)
- 位置:窗口最顶部(系统级区域);
- 功能:显示窗口名称(如“我的Qt应用”),包含系统默认的最小化、最大化/还原、关闭按钮;
- Qt 控制:可通过
setWindowTitle("标题")设置标题,也可自定义标题栏样式(需禁用系统标题栏)。
2. 菜单栏(Menu Bar)
常用函数
| 函数名 | 功能说明 |
|---|---|
| addMenu() | 向菜单栏添加菜单(支持传标题/图标+标题,或已创建的QMenu对象) |
| addSeparator() | 在菜单栏中添加分隔线(返回对应的特殊QAction) |
| insertMenu() | 在指定Action前插入菜单 |
| clear() | 清空菜单栏所有菜单、Action等内容 |
| activeAction() | 获取当前高亮的Action |
| setActiveAction() | 设置当前高亮的Action |
| setNativeMenuBar() | 设置是否使用系统原生菜单栏(如macOS顶部全局菜单) |
| actionAt() | 根据坐标获取对应位置的Action |
| setCornerWidget() | 在菜单栏角落(如右上角)设置自定义控件 |
常用信号
| 信号名 | 触发时机 |
|---|---|
| triggered(QAction *) | 菜单栏中某个Action被点击时发出 |
| hovered(QAction *) | 鼠标悬停到菜单栏的某个Action上时发出 |
Qt 中的菜单栏是通过 QMenuBar 来实现的。⼀个主窗⼝最多只有⼀个菜单栏。位于主窗⼝顶
部、主窗⼝标题栏下⾯。
菜单栏的创建:
- 可以直接通过Qt designer创建:(横向创建QMenu,纵向创建QAction)

- 也可以通过代码创建菜单栏以及菜单项:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//1.创建一个菜单栏
QMenuBar* menubar=new QMenuBar();
this->setMenuBar(menubar);
//2.创建菜单,添加menu
QMenu* menu1=new QMenu("文件");
menubar->addMenu(menu1);
QMenu* menu2=new QMenu("编辑");
menubar->addMenu(menu2);
QMenu* menu3=new QMenu("构建");
menubar->addMenu(menu3);
//3.给菜单添加菜单项
QAction* menu1_action1=new QAction("新建文件或项目");
menu1->addAction(menu1_action1);
QAction* menu1_action2=new QAction("打开文件或项目");
menu1->addAction(menu1_action2);
QAction* menu1_action3=new QAction("最近访问的文件");
menu1->addAction(menu1_action3);
//4.绑定信号与槽函数
connect(menu1_action1,&QAction::triggered,this,&MainWindow::handler);
}
void MainWindow::handler()
{
qDebug()<<"处理信号";
}

关于QMenuBar的创建:在创建QMainwindow的同时,自动创建了一个QMenuBar,如果直接在堆上开辟并调用 setMenuBar() 会失去对前者的控制,导致内存泄漏,因此推荐使用
QMenuBar* menubar=this -> menuBar(); this->setMenuBar(menubar);来创建
快捷键的设置:
- 类似于QLabel设置伙伴,在创建菜单栏/菜单项的文本后添加
(&快捷键),可以使用Alt + 快捷键选中菜单栏/菜单项。 - 也可以通过调用 setShortcut 设置快捷键
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar=new QMenuBar(this);
this->setMenuBar(menubar);
QMenu* menu1=new QMenu("文件(&F)");
menubar->addMenu(menu1);
QMenu* menu2=new QMenu("编辑(&E)");
menubar->addMenu(menu2);
QMenu* menu3=new QMenu("构建(&B)");
menubar->addMenu(menu3);
QAction* menu1_action1=new QAction("新建文件或项目(&)");
menu1->addAction(menu1_action1);
QAction* menu1_action2=new QAction("打开文件或项目");
menu1->addAction(menu1_action2);
QAction* menu1_action3=new QAction("最近访问的文件");
menu1->addAction(menu1_action3);
menu1_action1->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_N));
menu1_action2->setShortcut(QKeySequence(Qt::ControlModifier+Qt::Key_O));
connect(menu1_action1,&QAction::triggered,this,&MainWindow::handler);
}
子菜单的设置:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar=new QMenuBar(this);
this->setMenuBar(menubar);
QMenu* menu1=new QMenu("文件(&F)");
menubar->addMenu(menu1);
QMenu* menu2=new QMenu("编辑(&E)");
menubar->addMenu(menu2);
QMenu* menu3=new QMenu("构建(&B)");
menubar->addMenu(menu3);
QMenu* menuchild=new QMenu("子菜单");
QAction* menu1_action1=new QAction("新建文件或项目");
menuchild->addAction(menu1_action1);
QAction* menu1_action2=new QAction("打开文件或项目");
menuchild->addAction(menu1_action2);
QAction* menu1_action3=new QAction("最近访问的文件");
menuchild->addAction(menu1_action3);
menu1->addMenu(menuchild);//在这里加入到菜单栏
}

添加分割线/菜单栏图标:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menubar=new QMenuBar(this);
this->setMenuBar(menubar);
QMenu* menu1=new QMenu("文件(&F)");
menubar->addMenu(menu1);
QMenu* menuchild=new QMenu("子菜单");
menu1->addMenu(menuchild);
menuchild->setIcon(QIcon(":/favicon.png"));//通过qrc文件导入
QAction* menu1_action1=new QAction("新建文件或项目");
menuchild->addAction(menu1_action1);
menuchild->addSeparator();//注意每次在两个addAciton中间添加分割线
QAction* menu1_action2=new QAction("打开文件或项目");
menuchild->addAction(menu1_action2);
menuchild->addSeparator();//注意每次在两个addAciton中间添加分割线
QAction* menu1_action3=new QAction("最近访问的文件");
menuchild->addAction(menu1_action3);
}

3. 工具栏(Tool Bar)
常用函数
| 函数名 | 功能说明 |
|---|---|
| addAction() | 向工具栏添加动作(支持传文本/图标+文本,或已创建的QAction对象) |
| addSeparator() | 在工具栏中添加分隔线(用于分组Action,返回对应的特殊QAction) |
| addWidget() | 向工具栏添加自定义控件(如QPushButton、QLineEdit、QComboBox等) |
| setIconSize() | 设置工具栏中Action图标的统一尺寸(QSize类型,如QSize(32,32)) |
| setToolButtonStyle() | 设置工具栏按钮的显示样式(如仅显示图标、仅显示文本、图标+文本等) |
| addToolBarBreak() | 添加工具栏换行/分隔符(多工具栏并排时,将后续工具栏换到下一行) |
| setMovable() | 设置工具栏是否可拖动(默认可拖动,设为false则固定位置) |
| setFloatable() | 设置工具栏是否可浮动(设为true时,工具栏可拖出成为独立窗口) |
| clear() | 清空工具栏所有Action和自定义控件 |
| actionAt() | 根据坐标获取工具栏中对应位置的Action |
| setVisible() | 设置工具栏是否可见(true显示,false隐藏) |
| toggleViewAction() | 返回一个用于控制工具栏显示/隐藏的QAction(常用于菜单中控制工具栏) |
常用信号
| 信号名 | 触发时机 |
|---|---|
| actionTriggered(QAction *) | 工具栏中某个Action被点击/触发时发出 |
| topLevelChanged(bool) | 工具栏从“嵌入窗口”变为“浮动窗口”(或反之)时发出,参数表示是否为浮动状态 |
| visibilityChanged(bool) | 工具栏显示/隐藏状态改变时发出,参数表示是否可见 |
| movableChanged(bool) | 工具栏可拖动状态改变时发出,参数表示是否可拖动 |
| floatableChanged(bool) | 工具栏可浮动状态改变时发出,参数表示是否可浮动 |

创建工具栏,设置图标:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//QToolBar可以创建多个,且不会自动创建
QToolBar* toolbar=new QToolBar(this);
QAction* action1=new QAction("新建文件或项目");
toolbar->addAction(action1);
QAction* action2=new QAction("打开文件或项目");
toolbar->addAction(action2);
//图标会覆盖文字,设置的文字自动转为tooltip,也可以重新设定tooltip
action1->setIcon(QIcon(":/gridinsert.png"));
action2->setIcon(QIcon(":/downline.png"));
connect(action1,&QAction::triggered,this,&MainWindow::handler);
connect(action2,&QAction::triggered,this,&MainWindow::handler);
}

在使用过程中 工具栏的QAction也可以添加到QMenuBar中,绑定同一个槽函数,搭配使用
设置停靠位置:
| 枚举值 | 功能说明 |
|---|---|
| Qt::LeftToolBarArea | 工具栏停靠在窗口左侧 |
| Qt::RightToolBarArea | 工具栏停靠在窗口右侧 |
| Qt::TopToolBarArea | 工具栏停靠在窗口顶部 |
| Qt::BottomToolBarArea | 工具栏停靠在窗口底部 |
| Qt::AllToolBarAreas | 工具栏可停靠在以上四个位置 |
- 创建工具栏的同时指定停靠位置;
QToolBar *toolBar1 = new QToolBar(this);
QToolBar *toolBar2 = new QToolBar(this);
// 创建时指定在左侧显示
this->addToolBar(Qt::LeftToolBarArea,toolBar1);
// 创建时指定在右侧显示
this->addToolBar(Qt::RightToolBarArea,toolBar2);
- 通过QToolBar类的
setAllowedAreas()函数设置。
QToolBar *toolBar1 = new QToolBar(this);
QToolBar *toolBar2 = new QToolBar(this);
this->addToolBar(toolBar1);
this->addToolBar(toolBar2);
// 只允许在左侧停靠
toolBar1->setAllowedAreas(Qt::LeftToolBarArea);
// 只允许在右侧停靠
toolBar2->setAllowedAreas(Qt::RightToolBarArea);
设置浮动属性:
工具栏的浮动属性通过QToolBar类的setFloatable()函数设置:
QToolBar *toolBar1 = new QToolBar(this);
// 设置为浮动
toolBar1->setFloatable(true);
注意区别浮动与拖动的区别:浮动是工具栏可以在桌面任意位置移动,拖动只能停靠在允许停靠的未位置。
4. 中心部件(Central Widget)
- 位置:窗口中间的核心区域(布局中最大的部分);
- 核心要求:QMainWindow 必须设置且只能有一个中心部件,否则窗口会显示异常;
- 使用示例:
// 以 QTextEdit 作为中心部件(文本编辑器场景) QTextEdit *edit = new QTextEdit(this); this->setCentralWidget(edit); // 也可嵌套布局(比如放一个 QWidget 包含按钮+表格) QWidget *centralWidget = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(centralWidget); layout->addWidget(new QPushButton("按钮")); layout->addWidget(new QTableWidget); this->setCentralWidget(centralWidget);
5. 停靠窗口(Dock Widget)
在 Qt 中,浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗⼝⼀般是位于核⼼部件的周围,可以有多个。
常用函数
| 函数定义 | 作用说明 |
|---|---|
| QDockWidget(const QString &title, QWidget *parent = nullptr) | 创建浮动窗口实例,指定窗口标题和父部件 |
| void setWindowTitle(const QString &title) | 设置浮动窗口的标题 |
| QString windowTitle() const | 获取浮动窗口当前的标题 |
| void setAllowedAreas(Qt::DockWidgetAreas areas) | 设置浮动窗口允许停靠的区域(可通过` |
| Qt::DockWidgetAreas allowedAreas() const | 获取当前设置的允许停靠区域 |
| bool isAreaAllowed(Qt::DockWidgetArea area) const | 判断指定的单个区域是否被允许停靠 |
| void setFloating(bool floating) | 强制设置窗口的浮动状态(true=悬浮;false=停靠到主窗口) |
| bool isFloating() const | 判断窗口当前是否处于浮动状态 |
| void setWidget(QWidget *widget) | 为浮动窗口设置要嵌入的内容控件(QDockWidget作为容器的核心函数) |
| QWidget *widget() const | 获取当前嵌入到浮动窗口中的内容控件 |
| void setTitleBarWidget(QWidget *widget) | 替换浮动窗口默认的标题栏为自定义控件 |
| void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget) | (QMainWindow的函数)将浮动窗口添加到主窗口的指定初始停靠区域 |
| void QMainWindow::splitDockWidget(QDockWidget *first, QDockWidget *second, Qt::Orientation orientation) | (QMainWindow的函数)拆分已有浮动窗口,实现多窗口并列显示 |
常用信号
| 信号定义 | 触发时机 |
|---|---|
| void topLevelChanged(bool floating) | 浮动窗口的“浮动/停靠”状态发生变化时触发(如从停靠变悬浮、悬浮变停靠) |
| void visibilityChanged(bool visible) | 浮动窗口的可见性发生变化时触发(如窗口被显示/隐藏) |
| void allowedAreasChanged(Qt::DockWidgetAreas areas) | 浮动窗口允许停靠的区域被修改时触发 |
| void dockLocationChanged(Qt::DockWidgetArea area) | 浮动窗口的停靠位置发生变化时触发(如从左侧拖到右侧、顶部拖到底部) |
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDockWidget* dockwidget=new QDockWidget(this);
//可以使用addDockWidget来指定位置
this->addDockWidget(Qt::LeftDockWidgetArea,dockwidget);
//设置标题
dockwidget->setWindowTitle("dock widget");
//需要先添加一个widget到dockwidget,再添加子控件到widget
QWidget* widget=new QWidget();
dockwidget->setWidget(widget);
QPushButton* button=new QPushButton(widget);
button->setGeometry(widget->x(),widget->y(),200,200);
dockwidget->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::TopDockWidgetArea);
}

6. 状态栏(Status Bar)
重要函数
| 函数名 | 功能说明 |
|---|---|
| showMessage | 显示临时实时消息,设置timeout(ms)定时消失 |
| addWidget | 向状态栏左侧添加普通控件(可被临时消息覆盖) |
| addPermanentWidget | 向状态栏右侧添加永久控件(固定显示,不会被临时消息覆盖) |
| clearMessage | 立即清除当前显示的临时消息 |
| removeWidget | 移除已添加到状态栏的控件 |
| currentMessage | 获取当前显示的临时消息内容 |
重要信号
| 信号名 | 触发时机 |
|---|---|
| messageChanged | 状态栏的临时消息发生变化时触发(包括消息显示、更新、清除) |
状态栏是应用程序底部展示简要信息的区域,一个窗口最多仅能包含一个状态栏。在Qt中,状态栏通过QStatusBar类实现,支持显示三类信息:
- 实时消息:如当前程序运行状态(会自动消失);
- 永久消息:如程序版本、机构名称(持续显示);
- 进度消息:如进度条、百分比提示(展示任务进度)。
状态栏的创建:
通过QMainWindow的statusBar()函数创建状态栏实例,再用setStatusCode()将其挂载到窗口:
//同样因为ui会自动生成,采用自动生成的,防止内存泄漏
QStatusBar* statusbar=this->statusBar();
this->setStatusBar(statusbar);
显示实时消息:
通过showMessage()函数显示临时消息,需指定消息内容和显示时长(单位:毫秒),超时后消息自动消失:
// 在状态栏显示“Hello_Qt”,持续2000毫秒(2秒)
statusbar->showMessage("Hello_Qt", 2000);
显示永久消息:
永久消息需通过添加控件(如QLabel)实现,控件会持续显示在状态栏中:
// 1. 创建用于显示永久消息的标签
QLabel *label = new QLabel("提示信息", this);
// 2. 将标签添加到状态栏(默认显示在左侧)
stbar->addWidget(label);
调整永久消息的位置:
若要将控件显示在状态栏右侧,需使用addPermanentWidget()函数:
// 创建右侧显示的标签
QLabel *label2 = new QLabel("右侧提示信息", this);
// 将标签固定到状态栏右侧
stbar->addPermanentWidget(label2);
说明:addWidget()默认将控件放在状态栏左侧,addPermanentWidget()固定在右侧,两者可结合使用(如左侧显示提示、右侧显示版本号)。
三、Qt 窗口的关键特性
- 布局灵活性:QMainWindow 的布局是 Qt 预定义的“经典桌面布局”,无需手动写复杂的 QLayout 嵌套,直接调用
menuBar()、addToolBar()、setCentralWidget()等接口即可; - 组件可定制:所有组件支持隐藏/显示(比如隐藏工具栏
toolBar->hide()),适配不同场景; - 与 QWidget 的区别:
- QMainWindow:带预设布局,适合做“主窗口”(应用的顶层窗口);
- QWidget:空白窗口,无预设布局,适合做“子窗口/弹窗/中心部件的子控件”。
更多推荐


所有评论(0)