Qt窗口教程(上)

目录

添加快捷键

添加子菜单

添加分割线和图标

关于QMenuBar的创建和讨论

QToolBar的使用(工具栏)

[关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别](#关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别)

QStatusBar的使用(状态栏)

QDockWidget(浮动窗口)

浮动窗口的创建与停靠

[向浮动窗口添加控件(关键:中间容器 QWidget)](#向浮动窗口添加控件(关键:中间容器 QWidget))

用布局管理器组织控件(以垂直布局为例)

对话框

[一、QDialog 基础:是什么与怎么用](#一、QDialog 基础:是什么与怎么用)

自定义对话框的创建

二、关键问题:内存泄漏与解决方案

正确的内存管理:Qt::WA_DeleteOnClose

三、拓展:模态与非模态对话框

四、自定义对话

创建自定义对话框类

设计对话框界面与逻辑

在主窗口中调用自定义对话框

补充说明


前文的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的创建和讨论

  1. 自动生成 UI 文件的场景

    • 若项目勾选了自动生成 UI 文件,Qt 会自动创建一个QMenuBar并纳入对象树管理。
    • 此时若手动new QMenuBar并调用setMenuBar,会导致原有QMenuBar脱离对象树,无法被 Qt 自动释放,引发内存泄漏
  2. 正确的使用方式

    • 应通过this->menuBar()获取菜单 bar:
      • QMenuBar已存在,直接返回现有对象;
      • 若不存在,会先创建新对象再返回。
    • 调用setMenuBar时,若传入的是通过menuBar()获取的对象,相当于 "自己替换自己",仍会保持在对象树中,避免内存泄漏。
  3. 非自动生成 UI 文件的场景

    • 若未勾选自动生成 UI 文件,手动new QMenuBarsetMenuBar是可行的,不会引发内存泄漏。

QToolBar的使用(工具栏)

关于 Qt 中QToolBar(工具栏)与QMenuBar(菜单栏)的核心区别

  1. 数量限制与设置行为

    • 菜单栏(QMenuBar :一个窗口只能有一个。通过setMenuBar设置时,新的菜单栏会替换旧的set 操作隐含 "替换" 逻辑)。
    • 工具栏(QToolBar :一个窗口可以有多个 。通过addToolBar添加时,重复设置会新增工具栏(不包含 "替换" 逻辑)。
  2. 使用方式

    • 菜单栏:通过setMenuBar添加。
    • 工具栏:通过addToolBar添加,且支持手动移动位置。
  3. 存在性

    • 菜单栏:若未手动设置,窗口可无菜单栏;但通过setMenuBar设置后,全局唯一。
    • 工具栏:窗口可无工具栏,也可有多个。
  1. 停靠区域(ToolBarArea)

    • 可选位置:

      • Qt::LeftToolBarArea:停靠在左侧
      • Qt::RightToolBarArea:停靠在右侧
      • Qt::TopToolBarArea:停靠在顶部
      • Qt::BottomToolBarArea:停靠在底部
      • Qt::AllToolBarAreas:以上四个位置都可停靠
    • 可通过 setAllowedAreas 方法设置工具栏允许停靠的区域,例如:

      cpp 复制代码
      toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
  2. 浮动状态(Floatable)

    • 若工具栏被拖出并放置在窗口任意位置,称为 "浮动" 状态。

    • 可通过 setFloatable 方法设置是否允许浮动,例如:

      cpp 复制代码
      toolBar2->setFloatable(false); // 不允许浮动
  3. 可移动性(Movable)

    • 可通过 setMovable 方法设置工具栏是否可以移动,例如:

      cpp 复制代码
      toolBar2->setMovable(false); // 不允许移动
  4. 初始位置设置

    • MainWindow 提供 addToolBar 方法可设置工具栏的初始位置(上下左右等)。

QStatusBar的使用(状态栏)

  1. 获取与设置状态栏

    • 可通过 this->statusBar() 方法 "存在就获取,不存在就创建" 状态栏对象,示例:

      cpp 复制代码
      QStatusBar* statusBar = this->statusBar();
      this->setStatusBar(statusBar);
  2. 显示临时消息(showMessage

    • 功能:在状态栏中显示一段临时文本。
    • 参数:
      • 第一个参数为要显示的消息文本,如 "这是一个状态消息"

      • 第二个参数为消息显示的时长(单位:ms),若为 0(或不填),消息将持久存在。示例:

        cpp 复制代码
        statusBar->showMessage("这是一个状态消息", 3000); // 消息显示3秒后消失
  3. 添加子控件

    • 可向状态栏中添加其他 Qt 控件(如 QLabel),示例:

      cpp 复制代码
      QLabel* 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 表示停靠在主窗口左侧,你也可以选择 RightTopBottom 等区域。

向浮动窗口添加控件(关键:中间容器 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 的自定义类:

  1. 打开 Qt Creator,选择文件 → 新建文件或项目 ,在 "C++" 分类中选择C++ Class,点击 "Choose..."。
  2. 在 "Define Class" 界面中,设置:
    • Class nameDialog(自定义类名)
    • Base classQDialog(继承自 Qt 对话框基类)
    • 按需勾选头文件包含(如 Include QObjectInclude QDialog 等),然后点击 "下一步" 完成类的创建。
设计对话框界面与逻辑

在自定义的 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 设计师界面类")可视化设计对话框界面,再与自定义逻辑结合,提升开发效率。
相关推荐
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00616 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术16 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript