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 设计师界面类")可视化设计对话框界面,再与自定义逻辑结合,提升开发效率。
相关推荐
zizisuo2 小时前
16000+字!Java集合笔记
java·开发语言
星释2 小时前
Rust 练习册 :Nucleotide Codons与生物信息学
开发语言·算法·rust
熊猫钓鱼>_>2 小时前
Java面向对象核心面试技术考点深度解析
java·开发语言·面试·面向对象··class·oop
俊俊谢2 小时前
OpenCV环境配置(QT 6.6.1 MSVC2019 64bit + OpenCV – 4.12.0)
qt·opencv·msvc
她说彩礼65万2 小时前
C# 代理模式
开发语言·c#·代理模式
程序员大雄学编程2 小时前
用Python来学微积分34-定积分的基本性质及其应用
开发语言·python·数学·微积分
liu****2 小时前
12.线程(二)
linux·开发语言·c++·1024程序员节
DKPT2 小时前
如何设置JVM参数避开直接内存溢出的坑?
java·开发语言·jvm·笔记·学习
林一百二十八3 小时前
Python实现手写数字识别
开发语言·python