目录
[关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别](#关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别)
[向浮动窗口添加控件(关键:中间容器 QWidget)](#向浮动窗口添加控件(关键:中间容器 QWidget))
[一、QDialog 基础:是什么与怎么用](#一、QDialog 基础:是什么与怎么用)
前文的QWidGet是窗口的一部分。窗口结构图如下。

菜单栏的初步使用,捕获点击信号并进行响应
cpp
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
class Widget : public QMainWindow {
Q_OBJECT
public:
Widget(QWidget *parent = nullptr) : QMainWindow(parent) {
ui->setupUi(this);
// 1. 创建菜单栏
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);
// 连接"文件"菜单菜单项的点击信号
connect(action1, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "新建操作");
});
connect(action2, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "打开操作");
});
connect(action3, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "保存操作");
});
connect(action4, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "另存为操作");
});
connect(action5, &QAction::triggered, [=]() {
this->close(); // 点击退出关闭窗口
});
// 给"编辑"菜单添加菜单项并连接信号槽
QAction *editAction1 = new QAction("复制");
QAction *editAction2 = new QAction("粘贴");
menu2->addAction(editAction1);
menu2->addAction(editAction2);
connect(editAction1, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "复制操作");
});
connect(editAction2, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "粘贴操作");
});
// 给"视图"菜单添加菜单项并连接信号槽
QAction *viewAction1 = new QAction("显示工具栏");
QAction *viewAction2 = new QAction("显示状态栏");
menu3->addAction(viewAction1);
menu3->addAction(viewAction2);
connect(viewAction1, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "显示工具栏操作");
});
connect(viewAction2, &QAction::triggered, [=]() {
QMessageBox::information(this, "提示", "显示状态栏操作");
});
}
private:
// 假设存在 ui 成员,实际使用时需根据项目中 ui 类定义
// Ui::Widget ui;
};
添加快捷键
cpp
// 2. 创建菜单
QMenu *menu1 = new QMenu("文件(&F)");
QMenu *menu2 = new QMenu("编辑(&E)");
QMenu *menu3 = new QMenu("视图(&V)");
&字符=ALT+字符;
添加子菜单
cpp
//创建菜单栏
QMenuBar*menuBar=new QMenuBar(this);
this->setMenuBar(menuBar);
//设置主菜单
QMenu *menu1 = new QMenu("文件(&F)");
QMenu *menu2 = new QMenu("编辑(&E)");
QMenu *menu3 = new QMenu("视图(&V)");
//设置子菜单
QMenu *menu4 = new QMenu("新建(&C)");
QMenu *menu5 = new QMenu("打开(&O)");
QMenu *menu6 = new QMenu("关闭(&c)");
menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);
menu1->addMenu(menu4);
menu1->addMenu(menu5);
menu1->addMenu(menu6);

添加分割线和图标

代码:
cpp
ui->setupUi(this);
QMenuBar*mem=new QMenuBar(this);
this->setMenuBar(mem);
QMenu*menu=new QMenu("菜单");
mem->addMenu(menu);
QAction*action1=new QAction("编辑");
QAction*action2=new QAction("新建");
menu->addAction(action1);
//menu->addSeparator();
menu->addAction(action2);
主要作用是美化界面。
关于QMenuBar的创建和讨论
-
自动生成 UI 文件的场景
- 若项目勾选了自动生成 UI 文件,Qt 会自动创建一个
QMenuBar并纳入对象树管理。 - 此时若手动
new QMenuBar并调用setMenuBar,会导致原有QMenuBar脱离对象树,无法被 Qt 自动释放,引发内存泄漏。
- 若项目勾选了自动生成 UI 文件,Qt 会自动创建一个
-
正确的使用方式
- 应通过
this->menuBar()获取菜单 bar:- 若
QMenuBar已存在,直接返回现有对象; - 若不存在,会先创建新对象再返回。

- 若
- 调用
setMenuBar时,若传入的是通过menuBar()获取的对象,相当于 "自己替换自己",仍会保持在对象树中,避免内存泄漏。
- 应通过
-
非自动生成 UI 文件的场景
- 若未勾选自动生成 UI 文件,手动
new QMenuBar并setMenuBar是可行的,不会引发内存泄漏。
- 若未勾选自动生成 UI 文件,手动
QToolBar的使用(工具栏)
关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别
-
数量限制与设置行为
- 菜单栏(
QMenuBar) :一个窗口只能有一个。通过setMenuBar设置时,新的菜单栏会替换旧的 (set操作隐含 "替换" 逻辑)。 - 工具栏(
QToolBar) :一个窗口可以有多个 。通过addToolBar添加时,重复设置会新增工具栏(不包含 "替换" 逻辑)。
- 菜单栏(
-
使用方式
- 菜单栏:通过
setMenuBar添加。 - 工具栏:通过
addToolBar添加,且支持手动移动位置。
- 菜单栏:通过
-
存在性
- 菜单栏:若未手动设置,窗口可无菜单栏;但通过
setMenuBar设置后,全局唯一。 - 工具栏:窗口可无工具栏,也可有多个。
- 菜单栏:若未手动设置,窗口可无菜单栏;但通过
-
停靠区域(ToolBarArea)
-
可选位置:
Qt::LeftToolBarArea:停靠在左侧Qt::RightToolBarArea:停靠在右侧Qt::TopToolBarArea:停靠在顶部Qt::BottomToolBarArea:停靠在底部Qt::AllToolBarAreas:以上四个位置都可停靠
-
可通过
setAllowedAreas方法设置工具栏允许停靠的区域,例如:cpptoolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
-
-
浮动状态(Floatable)
-
若工具栏被拖出并放置在窗口任意位置,称为 "浮动" 状态。
-
可通过
setFloatable方法设置是否允许浮动,例如:cpptoolBar2->setFloatable(false); // 不允许浮动
-
-
可移动性(Movable)
-
可通过
setMovable方法设置工具栏是否可以移动,例如:cpptoolBar2->setMovable(false); // 不允许移动
-
-
初始位置设置
MainWindow提供addToolBar方法可设置工具栏的初始位置(上下左右等)。
QStatusBar的使用(状态栏)
-
获取与设置状态栏
-
可通过
this->statusBar()方法 "存在就获取,不存在就创建" 状态栏对象,示例:cppQStatusBar* statusBar = this->statusBar(); this->setStatusBar(statusBar);
-
-
显示临时消息(
showMessage)- 功能:在状态栏中显示一段临时文本。
- 参数:
-
第一个参数为要显示的消息文本,如
"这是一个状态消息"。 -
第二个参数为消息显示的时长(单位:ms),若为
0(或不填),消息将持久存在。示例:cppstatusBar->showMessage("这是一个状态消息", 3000); // 消息显示3秒后消失
-
-
添加子控件
-
可向状态栏中添加其他 Qt 控件(如
QLabel),示例:cppQLabel* label = new QLabel("这是一个 QLabel"); statusBar->addWidget(label);
-
QDockWidget(浮动窗口)
在 Qt 界面开发中,QDockWidget(浮动窗口)是实现界面模块化、可拖拽布局的重要组件。本文将详细介绍如何创建、配置浮动窗口,并在其内部添加控件与布局。
浮动窗口的创建与停靠
首先,我们需要创建 QDockWidget 实例,并将其添加到主窗口的指定区域:
cpp
// 1. 创建 QDockWidget 浮动窗口对象
QDockWidget* dockWidget = new QDockWidget();
// 2. 将浮动窗口添加到主窗口,指定停靠区域(如左侧)
this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
// 3. 为浮动窗口设置标题(可选,增强可读性)
dockWidget->setWindowTitle("这是一个浮动窗口");
这里的 Qt::LeftDockWidgetArea 表示停靠在主窗口左侧,你也可以选择 Right、Top、Bottom 等区域。
向浮动窗口添加控件(关键:中间容器 QWidget)
QDockWidget 不能直接添加子控件,必须借助一个中间 QWidget 作为容器:
cpp
// 1. 创建中间容器 QWidget
QWidget* container = new QWidget();
// 2. 将中间容器设置到 QDockWidget 中
dockWidget->setWidget(container);
用布局管理器组织控件(以垂直布局为例)
为了让控件布局更规范,我们可以结合 QVBoxLayout(垂直布局管理器)来管理控件:
cpp
// 1. 创建垂直布局管理器,并设置到中间容器
QVBoxLayout* layout = new QVBoxLayout();
container->setLayout(layout);
// 2. 创建控件并添加到布局中
QLabel* label = new QLabel("这是一个标签");
QPushButton* button = new QPushButton("点击按钮");
layout->addWidget(label);
layout->addWidget(button);
布局管理器会自动处理控件的位置和大小,即使窗口缩放也能保持良好的布局效果。
对话框
在 Qt 开发中,对话框(QDialog)是实现 "短平快" 用户交互的核心组件,比如网站弹出的各种提示窗口,在 Qt 中都可以通过 QDialog 来实现。本文将带你从基础使用到内存管理,全面掌握 QDialog 的应用。
一、QDialog 基础:是什么与怎么用
Qt 中用 QDialog 类表示对话框,它是 QWidget 的子类,因此可以使用 QWidget 的所有属性和方法。
对话框的典型用途是实现 "短平快" 的交互,比如文件保存提示、颜色选择、消息提示等。Qt 还提供了很多现成的内置对话框,比如:
QFileDialog(文件对话框)QColorDialog(颜色对话框)QFontDialog(字体对话框)QInputDialog(输入对话框)QMessageBox(消息框)
自定义对话框的创建
实际开发中,我们通常会创建自定义类继承自 QDialog 来实现业务逻辑(而非直接在主窗口中继承 QDialog)。主窗口可以动态弹出这些自定义对话框,示例如下:
cpp
void MainWindow::on_pushButton_clicked() {
// 创建 QDialog 实例,父对象设为主窗口(this)
QDialog* dialog = new QDialog(this);
// 设置对话框标题
dialog->setWindowTitle("自定义对话框");
// 设置对话框尺寸
dialog->resize(400, 300);
// 显示对话框
dialog->show();
}
二、关键问题:内存泄漏与解决方案
如果像上面这样直接创建 QDialog,会存在内存泄漏风险 ------ 每次点击按钮都会创建新的 QDialog 对象,若频繁操作,会产生大量未释放的对象。
虽然将父对象设为 this(主窗口)后,主窗口销毁时会自动释放这些对话框,但如果对话框在主窗口销毁前就大量存在(比如嵌入式设备内存紧张的场景),仍会引发内存问题。
正确的内存管理:Qt::WA_DeleteOnClose
Qt 提供了一个便捷的属性 Qt::WA_DeleteOnClose,设置后对话框在关闭时会自动销毁,彻底解决内存泄漏问题:
cpp
void MainWindow::on_pushButton_clicked() {
QDialog* dialog = new QDialog(this);
dialog->setWindowTitle("自动销毁的对话框");
dialog->resize(400, 300);
// 设置"关闭时自动删除"属性
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
}
这样,用户关闭对话框时,Qt 会自动释放其内存,无需手动调用 delete(避免了 "对话框一闪而过" 的问题)。
三、拓展:模态与非模态对话框
QDialog 支持模态 和非模态两种显示方式:
- 模态对话框:弹出后会阻塞主窗口,必须关闭对话框才能操作主窗口(比如系统的 "是否保存" 提示)。
- 非模态对话框:弹出后不阻塞主窗口,可同时操作对话框和主窗口(比如悬浮的工具面板)。
若需实现模态对话框,可将 show() 替换为 exec():
cpp
void MainWindow::on_pushButton_clicked() {
QDialog* dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->exec(); // 模态显示,阻塞主窗口
}
通过以上步骤,我们可以在 Qt 中高效、安全地使用对话框,既满足 "短平快" 的交互需求,又能避免内存泄漏的隐患。
在 Qt 开发中,自定义对话框是实现个性化用户交互的关键。下面我们从创建自定义对话框类开始,一步步完成一个可交互的对话框功能。
四、自定义对话
创建自定义对话框类
首先在 Qt Creator 中创建一个继承自 QDialog 的自定义类:
- 打开 Qt Creator,选择文件 → 新建文件或项目 ,在 "C++" 分类中选择C++ Class,点击 "Choose..."。
- 在 "Define Class" 界面中,设置:
- Class name :
Dialog(自定义类名) - Base class :
QDialog(继承自 Qt 对话框基类) - 按需勾选头文件包含(如
Include QObject、Include QDialog等),然后点击 "下一步" 完成类的创建。
- Class name :
设计对话框界面与逻辑
在自定义的 Dialog 类中,我们可以添加控件并实现交互逻辑:
cpp
// Dialog.h 中声明类结构
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = nullptr);
private slots:
void handle(); // 按钮点击的槽函数
private:
QVBoxLayout *layout;
QLabel *label;
QPushButton *button;
};
// Dialog.cpp 中实现界面与逻辑
Dialog::Dialog(QWidget *parent) : QDialog(parent)
{
// 创建垂直布局管理器
layout = new QVBoxLayout(this);
this->setLayout(layout);
// 添加标签和按钮控件
label = new QLabel("这是一个自定义对话框", this);
button = new QPushButton("关闭", this);
layout->addWidget(label);
layout->addWidget(button);
// 连接按钮点击信号与槽函数
connect(button, &QPushButton::clicked, this, &Dialog::handle);
}
void Dialog::handle()
{
this->close(); // 点击按钮时关闭对话框
}
在主窗口中调用自定义对话框
在主窗口(如 MainWindow)中,通过按钮点击事件触发对话框的显示:
cpp
void MainWindow::on_pushButton_clicked()
{
Dialog* dialog = new Dialog(this); // 创建对话框实例,父对象为主窗口
dialog->resize(400, 300); // 设置对话框尺寸
dialog->setAttribute(Qt::WA_DeleteOnClose); // 设置关闭时自动释放内存
dialog->show(); // 显示对话框(非模态)
// 若需模态显示,可替换为 dialog->exec();
}
补充说明
- 内存管理 :通过
setAttribute(Qt::WA_DeleteOnClose)确保对话框关闭时自动释放内存,避免泄漏。 - 模态与非模态 :
show()实现非模态显示(不阻塞主窗口),exec()实现模态显示(阻塞主窗口,需关闭对话框才能操作主窗口)。 - 界面拓展:可通过 Qt Designer 模板("Qt 设计师界面类")可视化设计对话框界面,再与自定义逻辑结合,提升开发效率。