Qt — Qt 窗口

目录

[1. Qt 窗口概述](#1. Qt 窗口概述)

[2. 菜单栏](#2. 菜单栏)

[2.1 图形化界面实现菜单栏:](#2.1 图形化界面实现菜单栏:)

[2.2 代码的方式实现菜单栏](#2.2 代码的方式实现菜单栏)

[2.3 给菜单添加快捷键:](#2.3 给菜单添加快捷键:)

[2.4 菜单项进行快捷键的设置:](#2.4 菜单项进行快捷键的设置:)

[2.5 添加子菜单](#2.5 添加子菜单)

[2.6 添加分割线](#2.6 添加分割线)

[2.7 添加图标](#2.7 添加图标)

[2.8 QMenuBar 的创建方式的修改](#2.8 QMenuBar 的创建方式的修改)

[3. 工具栏](#3. 工具栏)

[3.1 添加1个工具栏](#3.1 添加1个工具栏)

[3.2 添加多个工具栏](#3.2 添加多个工具栏)

[3.3 代码实现方式:](#3.3 代码实现方式:)

[4. 状态栏](#4. 状态栏)

[5. 浮动窗口](#5. 浮动窗口)

[6. 对话框](#6. 对话框)

[6.1 对话框的介绍](#6.1 对话框的介绍)

[6.2 对话框的分类](#6.2 对话框的分类)

[6.3 Qt 内置对话框](#6.3 Qt 内置对话框)

[6.3.1 消息对话框 QMessageBox](#6.3.1 消息对话框 QMessageBox)

[6.3.2 颜色对话框 QColorDialog](#6.3.2 颜色对话框 QColorDialog)

[6.3.3 文件对话框 QFileDialog](#6.3.3 文件对话框 QFileDialog)

[6.3.4 字体对话框 QFontDialog](#6.3.4 字体对话框 QFontDialog)

[6.3.4 输入对话框 QInputDialog](#6.3.4 输入对话框 QInputDialog)


前面的文章,都是基于 QWidget 控件,QWidget 更多的是作为别的窗口的一个部分

1. Qt 窗口概述

Qt 窗口 是通过 QMainWindow类 来实现的。

QMainWindow 是⼀个为用户提供主窗口程序的类,继承自 QWidget 类, 并且提供了⼀个预定义的布局。**QMainWindow 包含 ⼀个菜单栏(menu bar)、多个⼯具栏(tool bars)、多个浮动窗⼝(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个 中⼼部件(central widget),**它是许多应⽤程序的基础,如文本编辑器,图片编辑器等。如下图为 QMainwindow 中 各组件所处的位置:

Mebu Bar:菜单栏

Qt 中:

Tool Bar Area:工具栏,可放在粉色区域中的上下左右任何位置即可

工具栏,类似于菜单栏。

画图 中:

工具栏的本质就是把菜单中的一些比较常用的选项,直接放到工具栏里,直接点击工具栏中的按钮就能快速生效。

Dock Widget Area:铆接部件,就是子窗口,上下左右都可以产生子窗口,不过上边的子窗口比较少

Central Widget:中央控件,窗口最核心的部分
Status Bar:状态栏

画图中的:

2. 菜单栏

Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。**⼀个主窗口最多只有⼀个菜单栏。**位于主窗⼝顶部、主窗⼝标题栏下⾯。

菜单栏中包含菜单. 菜单中包含菜单项.

QMenu:菜单

QMenuBar:菜单栏

QAction:菜单项(动作)

2.1 图形化界面实现菜单栏:

上述代码中,感觉没啥区别,但是实际上是有区别的,区别体现在ui文件中,ui 文件中多出来的选项,这个选项就可以给菜单栏添加菜单了:

菜单栏(QMenuBar)-> 菜单(QMenu)-> 菜单项(QAction)

添加菜单项:

运行:

2.2 代码的方式实现菜单栏

运行:

但是可以发现,点击菜单项没有任何的反应,再点击菜单项的时候会触发 triggered 触发:

2.3 给菜单添加快捷键:

在记事本中就有对应的快捷键:

按住 ALT + F,弹出对应菜单的菜单项

通过给文本添加 &F 这样的操作,就是添加了快捷键 alt + F,通过之前的讲述的 QShortCut 也可以实现类似的效果,但是太麻烦了。

运行,按住 ALT + 上述设置的快捷键字母:

2.4 菜单项进行快捷键的设置:

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("编辑 (&E)");
    QMenu* menu3 = new QMenu("视图 (&V)");
    QMenu* menu4 = new QMenu("帮助 (&H)");
    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
    menuBar->addMenu(menu3);
    menuBar->addMenu(menu4);

    // 创建菜单项
    QAction* action1 = new QAction("新建(&A)");
    QAction* action2 = new QAction("保存(&S)");
    QAction* action3 = new QAction("另存为(&X)");
    QAction* action4 = new QAction("退出(&C)");
    QAction* action5 = new QAction("ACtion5(&D)");
    QAction* action6 = new QAction("Action6(&K)");
    menu1->addAction(action1);
    menu1->addAction(action2);
    menu2->addAction(action3);
    menu2->addAction(action4);
    menu3->addAction(action5);
    menu4->addAction(action6);

    connect(action1, &QAction::triggered, this, &MainWindow::action1);
    connect(action2, &QAction::triggered, this, &MainWindow::action2);
    connect(action3, &QAction::triggered, this, &MainWindow::action3);
    connect(action4, &QAction::triggered, this, &MainWindow::action4);
    connect(action5, &QAction::triggered, this, &MainWindow::action5);
    connect(action6, &QAction::triggered, this, &MainWindow::action6);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::action1()
{
    qDebug() << "action1";
}

void MainWindow::action2()
{
    qDebug() << "action2";
}

void MainWindow::action3()
{
    qDebug() << "action3";
}

void MainWindow::action4()
{
    qDebug() << "action4";
}

void MainWindow::action5()
{
    qDebug() << "action5";
}

void MainWindow::action6()
{
    qDebug() << "action6";
}

运行:

2.5 添加子菜单

菜单栏 -> 菜单 -> 子菜单 -> 在菜单 -> 菜单项。

QMenuBar 可以通过 addMenu 添加菜单的,同样 QMenu 也是提供了 addMenu,通过这个操作给某个菜单项添加子菜单,但是实际情况中是不会给菜单项套多个子菜单的,因为看上去太复杂了。

运行:

2.6 添加分割线

菜单里菜单项特别多,就可以通过分割线,进行分组,Qmenu 中提供 addSeparator 这样的函数:

运行:

2.7 添加图标

用到 QIcon 类 + qrc 机制:

运行:

其实 Qmenu 也是可以进行设置图标的:

运行:

但是给 Qmenu 设置图标,当前 QMenu 是长在 QmenuBar 上的,此时图标覆盖了文本,此时的稳步就不显示了,QMenu 是子菜单,图标和文本是都能显示的。

2.8 QMenuBar 的创建方式的修改

之前的代码中创建 menuBar 的方式是这样的:

如果我们创建的项目,没有勾选自动生成的 ui 文件,此时上述代码是ok的,但是我们勾选了自动生成 ui 文件,上述代码就会引起 内存泄漏。

勾选自动生成 ui 文件:意味着 Qt 已经给我们生成另一个 QMenuBar 了,在 QtDesigner 中可以看见:

程序自己已经创建好了一个 QMenuBar,当设置新的 QMenuBar 进来的时候,就会导致旧的 QMenuBar 脱离了 Qt 的对象树了,意味着后续就无法对这个对象进行释放了。

上述程序如果窗口关闭,对象数释放,此时进程也就结束了,进程结束,自然所有内存都会受给系统,上述内存泄露也不会造成影响

但是如果这样的代码是出现在一个多窗口的程序中,如果涉及到窗口的频繁跳转切换(窗口的频繁创建销毁),上述内存泄露就会更严重一些。但是实际上由于现在的计算机内存都比较充裕,上述内存泄漏都还好。服务器程序相比于客户端程序更害怕内存泄漏,原因1:服务器要处理很多请求,每个请求泄露一点,请求积累下来就会泄露很多;原因2:服务器要 7*24 小时运行

当然,即使如此,还是应该将代码写的更加规范一些:

此时:

  • 如果 QMenuBar 已经存在,直接获取并返回
  • 如果 QMenuBar 不存在,就先创建一个新的,再返回
  • 如果是获取到已经存在的 QMenuBar,这里的设置就是自己替换自己,还是自己,仍然是在对象树上的。

3. 工具栏

⼯具栏是应⽤程序中集成各种功能实现快捷键使⽤的⼀个区域。可以有多个,也可以没有,它并不是应⽤程序中必须存在的组件。它是⼀个可移动的组件,它的元素可以是各种窗⼝组件,它的元素通常

以图标按钮的⽅式存在。如下图为⼯具栏的⽰意图:

使用 QToolBar 表示工具栏对象,一个窗口可以有多个工具栏,也可以没有。

工具栏往往也可以手动移动位置。

3.1 添加1个工具栏

添加菜单栏,使用的是 setMenuBar。(菜单栏只能有一个,重复设置,新的替换旧的,set 就包含了"替换"的含义)

添加工具栏,使用的是 addToolBar。(add 不包含"替换"的含义)

典型的工具栏展示的不是文本,而是图标。

运行:

可以看见,QAction 如果出现在工具栏上,也会产生文本虽然被图片覆盖掉的情况,但是当鼠标悬停在图标上面是有提示的文字的,但是也可以手动的进行 Tooltip :

运行:

覆盖了之前显示的文字。

工具栏往往也是和菜单栏搭配使用的,工具栏中的 QAction 也可以出现在菜单中:

运行:

一个 QAction 既是 QMenu 的子元素,又是 QToolBar 的子元素,释放的时候,只会被释放一次,不会重复 delete。

3.2 添加多个工具栏

运行:

是可以进行拖动的,工具栏拖出来可以放到窗口的任意位置,称之为是 "浮动" 状态。

工具栏允许停放到哪些边缘:

3.3 代码实现方式:

  1. 可以设置工具栏出现的初始位置(上下左右)

MainWindow 提供了 addToolBar

Qt::ToolBarArea area 指定出当前的位置,位置的选项有:

  • Qt::LeftToolBarArea 停靠在左侧
  • Qt::RightToolBarArea 停靠在右侧
  • Qt::TopToolBarArea 停靠在顶部
  • Qt::BottomToolBarArea 停靠在底部
  • Qt::AllToolBarAreas 以上四个位置都可停靠

初始位置为右:

  1. 可以设置工具栏允许停放到哪些边缘

QToolBar 有一个自己的方法:setAllowedAreas

只能停靠在左右两侧,不能停靠在上下两侧。

  1. 可以设置工具栏是否允许浮动
  1. 可以设置工具栏是否可以移动

不移动是包括不能浮动 和 不能停靠在任意一侧。

4. 状态栏

运行:

可以指定一个时间:

通过 showMessage 可以在状态栏中显示一个文本,此时这个文本存在的时间可以自定义,timeout 参数是一个单位为 ms 的时间,如果 timeout 为0(不填),消息就会持久存在。

3秒之后,消息自动消失:

状态栏中还可以添加其它控件:

addWidget:从左往右添加控件

addPermanentWidget:从右往左添加控件

运行:

5. 浮动窗口

浮动窗口就是子窗口,在 Qt 中,浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗⼝⼀般是位于核⼼部件的周围,可以有多个。

由于 dockWidget 中只能包含一个 QWidget,要想添加更多的控件就只能往 QWidget 中进行添加了(多套一层)

运行:

此时浮动窗口就只能在左边或者是上边。

6. 对话框

6.1 对话框的介绍

对话框是 GUI 程序中不可或缺的组成部分。⼀些不适合在主窗⼝实现的功能组件可以设置在对话框中。对话框通常是⼀个顶层窗⼝,出现在程序最上层,⽤于实现短期任务或者简洁的用户交互。

某些网站不经意之间弹出来的窗口,就是对话框,往往用于和用户之间进行 "短平快" 的操作,例如:写博客中未保存退出就会出现对话框:

Qt 中使用 QDialog类表示对话框。针对一个已有的项目,也可以创建一些类,继承自 QDialog 实现我们自定义的对话框。Qt 也提供了很多现成的对话框。

Qt常⽤的内置对话框有:QFiledialog(⽂件对话框)、QColorDialog(颜⾊对话框)、QFontDialog(字体对话框)、QInputDialog (输⼊对话框)和 QMessageBox(消息框)。

直接运行:

总体来说,基于 QDialog 作为父类创建出来的程序窗口和之前通过QWidget 创建出来的非常相似的。

也是有自身的属性的:

实际开发中,往往不是直接在创建项目的时候继承自QDialog,而是在代码中,创建额外的类,让额外的类继承自 QDialog。也就是说主窗口,一般不会作为一个对话框,主窗口可以产生一些其它的对话框。

eg:主窗口中,通过点击按钮,弹出一个新的对话框

运行:

QDialog 其实也是 QWidget 的子类,QWidget 的各种属性方法,QDialog 也能使用。

对话框的内存释放的问题:

弹出对话框,点击关闭就没了,再一点又弹出来,再点击关闭也就没有了,两次弹出的对话框,都会创建一个新的 QDialog 对象,并进行显示,这一点和其它的控件不同。每次点击都会创建新的对话框对象!!!一个程序运行过程中,可以无数次点击这个按钮,进一步的就产生出无数个这样的对象了!!!就会涉及到内存泄漏的问题!!!

确实,是把父元素设为 this,QMianWindow 被销毁的时候,此时QDialog 是会随之销毁,但是架不住 QDialog 会在 QMainWindow 之前就存在很多个。

释放的操作:让用户点击对话框关闭按钮的时候,再来触发这里的 delete 操作

只要给 dialog 设置上述属性,此时就会在关闭的时候自动进行 delete,Qt 内置的功能。

要想自定义对话框,就需要继承自 QDialog 创建类:

  • 纯代码的方式来自定义 QDialog 界面

运行:

  • 通过图形化的方式:关键操作是新建一个 ui 文件出来

创建出一个 ui 文件 以及对应的类:

运行:

6.2 对话框的分类

模态对话框

  1. 模态:弹出对话框的时候,此时用户无法操作父窗口,必须得完成对话框内部的操作,关闭对话框之后,才能操作父窗口。用于特别关键的场合,用户必须要做出决策。
  2. 非模态:弹出对话框,用户可以操作父窗口。用于不是特别关键的场景。

前面写的几个代码,都是"非模态"对话框

如何产生模态对话框???

将 ->show() 换成 ->exec() 方法:

6.3 Qt 内置对话框

Qt 提供了多种可复⽤的对话框类型,即 Qt 标准对话框。Qt 标准对话框全部继承于 QDialog类。常⽤标准对话框如下:

6.3.1 消息对话框 QMessageBox

QMessageBox 用来显示一个消息给用户,并且让用户进行一个简单的选择。

运行:

给对话框设置自定义按钮:

第二个参数是枚举类型:

运行:

运行:

更简洁的写法:

运行:

6.3.2 颜色对话框 QColorDialog

颜⾊对话框的功能是允许用户选择颜⾊。继承⾃ QDialog 类。颜⾊对话框如下图示:

getColor 这个函数就能够弹出一个模态对话框,用户选择颜色之后,点击确定,对话框关闭,getColor 返回的只就是用户选择的颜色值!!! getColor 是一个 static 静态函数,跟 QMessageBox::warning 类似的效果,不必创建对话框对象,就可以直接使用。

运行:

ARGB :alpha 不透明度(opcity)

剩下的三个就是 RGB,是通过 0-1 这样小数的形式来表示RGB的值了。

运行:

6.3.3 文件对话框 QFileDialog

⽂件对话框⽤于应⽤程序中需要打开⼀个外部⽂件或需要将当前内容存储到指定的外部⽂件。

通过 QFileDialog 可以选择一个文件,能够获取到这个文件的路径,进而能够打开/保存文件。

1、打开⽂件(⼀次只能打开⼀个⽂件)

QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr,QFileDialog::Options options = Options())

2、打开多个⽂件(⼀次可以打开多个⽂件)

QStringList getOpenFileNames(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr,QFileDialog::Options options = Options())

3、 保存⽂件

QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), constQString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr,QFileDialog::Options options = Options())

参数说明:

  • 参数1:parent ⽗亲
  • 参数2:caption 对话框标题
  • 参数3:dir 默认打开的路径
  • 参数4:filter ⽂件过滤器

运行:

点击打开文件:

点击保存文件:

此处的打开/保存这里的功能都是需要额外去实现的,并不是说直接一按保存就真的保存了。

6.3.4 字体对话框 QFontDialog

运行:

6.3.4 输入对话框 QInputDialog

让用户输入具体的数据,可以是整数,可以使浮点数,还可以是字符串(以类似于下拉框的方式呈现)

常⽤⽅法介绍:

1、双精度浮点型输⼊数据对话框

double getDouble (QWidget *parent, const QString &title, const QString &label, double value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());

2、整型输⼊数据对话框

int getInt (QWidget *parent, const QString &title, const QString &label, int value = 0, int min = -2147483647, int max = 2147483647, int step = 1, bool *ok = nullptr, Qt::WindowFlags
flags = Qt::WindowFlags());

3、选择条⽬型输⼊数据框

QString getItem (QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current = 0, bool editable = true, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints =
Qt::ImhNone) ;

QStringList:当成是一个字符串数组,QList<QString>

参数说明:

  • parent:⽗亲
  • title:对话框标题
  • label:对话框标签
  • items:可供选择的条⽬

运行:

相关推荐
2601_962218611 小时前
C++中分配器allocator的实现
开发语言·c++
wshzd1 小时前
LLM之Agent(104)|DeepSeek-Harness(十三)ReactLoopAgent 总览:kick → turn → step
开发语言·前端·javascript
共享家95271 小时前
C语言-408
c语言·开发语言
周杰偷奶茶1 小时前
【Java】运算符指南
java·开发语言
2601_966949652 小时前
量化回测中分钟数据应该如何保存?从文件到数据仓库的工程化设计
开发语言·python·pandas·量化交易·股票数据·quantdash
Zhou1411362 小时前
SpringMVC_02_注解开发实战
开发语言·windows·python
繁华的地方不一定留下你的脚印2 小时前
C++ 算法与 ranges:用 find_if、transform 写清数据处理意图
开发语言·c++·算法
霸道流氓气质2 小时前
Mermaid 图表完全指南:从文本语法到LangGraph4j工作流可视化实战
开发语言·python
泡海椒3 小时前
JQuick-Excel 项目定位与适用场景:声明式 Java Excel 的边界
java·开发语言·excel