Qt 窗口

在Qt Creator 中创建项目的时候,我们能够选择创建QMainWindow 还是 QWidget 两种窗口。

二者有什么区别呢?其中 QMainWindow 是一种主窗口,包含菜单栏,工具栏,状态栏,中心窗口和浮动窗口等多个窗口组合,它继承自QWidget类,提供了一个预定义的布局。这就是二者的区别。 

一个成熟的窗口,必然包含菜单栏、工具栏、状态栏等多个窗口组合在一起,因此我们使用 Qt 创建一个窗口时,必然需要考虑这些要素,那么本文我们就来学习如何创建一个成熟的Qt窗口吧。

菜单栏

Qt 中,菜单栏采用 QMenuBar 这个类实现,一个菜单栏中可以包含多个菜单,而一个菜单中又包含多个菜单项或者子菜单。

  • QMenuBar : 菜单栏类
  • QMenu:菜单类
  • QAction : 菜单项类

我们可以通过 Qt Designer 来创建一个菜单栏。(注意,必须是 QMainWindow 才行)

 在 Qt Designer 中的左上角,点击 "在这里输入即可在菜单栏这里添加菜单,添加完菜单后即可点击下面的 "在这里输入" 即可添加菜单项,也可以继续输入来添加子菜单。

不过这里有一个 Bug,即无法输入中文,只能采用复制粘贴的方式来输入中文。

添加菜单栏、菜单和菜单项 

此外,也可以通过代码的形式来添加菜单。

 

能够获取到确实添加了菜单栏、菜单和菜单项。 

添加快捷键

在 Qt 的菜单栏中,我们可以通过快捷键来快速选取,比如下面的菜单可以通过 Alt + F 来选取文件菜单Alt + E 来选取编辑菜单按下对应的快捷键直接选取菜单项,我们也能够自行设置快捷键方便我们使用。

和 label 控件一样,都是通过 & + 快捷键的方式来设置对应的快捷键,这样就能够通过 Alt + 快捷键的方式选中菜单了。不过有一点需要注意,同时出现的快捷键之间不能重名,比如菜单之间的快捷键不能相同,但是不同菜单下的菜单项的快捷键可以相同。

 

三个菜单项被选中就会输出对应的消息。 

可以看到确实被选中了并且输出了消息。

添加子菜单

一般菜单中也会嵌套子菜单,比如 Qt 的文件中,就存在访问最近打开文件的子菜单,我们也能够手动添加子菜单。

先创建一个新的 QMenu 对象,并且添加菜单项,然后将该 QMenu 对象添加到某个菜单下面,就添加了一个子菜单。

 这样就能够看到一个子菜单。

添加图标

有的窗口能够显示出图标,比如浏览器的收藏夹。

这些网站就有它们自己的图标,我们也能给自己的菜单添加图标。

 通过 qrc 机制获取图片,然后设置给对应的菜单项。

可以看到图标已经被设置好了。 

 不过一般菜单是不设置图标的,比如这里可以看到给一个菜单设置了图标。

但是图标将文字覆盖了,因此菜单不设置图标。 

添加分割线

QMenu 类中有一个函数叫 addSeparator() ,它会添加一个分割线。

比如这里在添加菜单项的时候,中间添加一个分割线。

能够看到在保存和打开之间多出了一条很浅的分割线。 

 QMenuBar 的一些问题

在上面的代码中,我们都是先创建一个 QMenuBar,然后再设置即可,但是这是有一点问题的。

在创建项目的时候,没有勾选自动生成ui文件的时候,这里是没问题的,而如果勾选了生成 ui 文件的时候,就会出现内存泄漏,比如我这里是勾选了自动生成 ui 文件了的。

Qt 会自动生成一个 QMenuBar 对象,并且挂在 MainWindow 上,而如果按照我上面的代码写,那么我们手动生成的 QMenuBar 对象就会替换掉自动生成的 QMenuBar 对象,这个自动生成的 QMenuBar 就不存在对象树上了,那么它就无法自动释放,就会造成内存泄漏。

为了针对这个问题,我们可以采用其他方式创建 QMenuBar 对象。

即通过 this->menuBar() 来获取this自带的menuBar,如果自动生成了,那么我们就获取到了这个 menuBar,没有创建新的资源,自动生成的 menuBar 就不会出问题了。

而如果没有自动生成 menuBar,就会自动生成然后返回。

 这样两者方式都没有造成内存泄漏。

工具栏

工具栏一行包含一系列快捷工具,一般都是菜单栏中的常用菜单项,因此工具栏的工具项一般和菜单项都采用 QAction 类,都是通用的。

而一个窗口可以含有0个或者多个工具栏,这些工具栏的位置可以随时拖动修改,也就是所谓的浮动态。

创建工具栏并添加工具

和菜单栏不同,工具栏能够同时存在多个,因此添加工具栏的函数是 addToolBar 而非 setToolBar

而工具项和菜单项都是类似的,因此都是用的 QAction 类。

设置工具栏位置

工具栏和菜单栏不同,工具栏可以自由设置不同的位置,在添加工具栏的时候可以设置位置。 

 一般可以添在四种位置,默认在上方。

  • Qt::LeftToolBarArea  :  左侧
  • Qt::RightToolBarArea : 右侧
  • Qt::TopToolBarArea : 上侧
  • Qt::BottomToolBarArea : 底侧
  • Qt::AllToolBarArea : 四个位置都能停靠

除了在添加工具栏的时候 ,我们也能够设置工具栏允许停靠的位置。

通过 setAllowedAreas 可以设置允许其停靠的位置,比如下面的代码就允许停靠 左右区域。

可以发现,虽然刚开始的时候工具栏在上方,但是一旦拖动之后就无法回到上方了。 

  • addToolBar : 是设定初识工具栏的位置
  • setAllowedAreas : 是设定允许工具栏停靠的位置 

其中,工具栏没有固定在某个位置时,称为浮动态,能不能浮动我们也能设置。 

设定工具项的图标

给工具栏添加工具项的时候,也可以为他设置图标,毕竟大部分工具都是采用图标显示的。

不过图标会覆盖工具项的文字,此外,最初设置的文字会变成工具项的 toolTip,即提示。

我们也能通过 setToolTip 函数设置提示信息。

设置工具栏的浮动属性

工具栏并不唯一,我们可以设置多个工具栏。

可以看到,不同的工具栏的前面都有一根竖着的线。

拖拽该线即可移动工具栏,如果拖动的工具栏没有固定在某个方向,那么该工具栏就会变成浮动态,我们也可以通过手动设置是否允许浮动。

比如这里设置 toolbar1 不可浮动。

发现第一个工具栏无法浮动 

 

设置工具栏的移动属性 

这里设置工具栏2 的移动属性为false。 

发现第二个工具栏直接没有移动的选项了。 

 

状态栏 

状态栏是位于窗口底层,用于显示程序的一些简单信息的区域。

它可以显示实时消息、永久消息或者进度条消息等。

状态栏的创建

和菜单栏一样,一个窗口只能有一个状态栏,因此它的创建只能通过 setStatusBar 设置。

设置实时消息

通过 showMessage 函数可以设置信息,其超时时间以ms为单位,如果设置超时时间为0,则默认一直显示。

 设置永久信息

一般永久信息都是通过 label 来显示的,不过有一点需要注意,这种信息会被 showMessage 的显示信息给覆盖掉,因此需要注意。

StatusBar 都能够添加控件,通过 addWidget 函数添加控件,一般所有控件都能够添加。

其次,添加控件的时候,我们能够添加控件的拉伸系数。

 可以看到第一个 label 和第二个 label 不同。

浮动窗口

一般一个窗口中可以有多个小窗口,比如 Qt Creator 就含有多个浮动窗口。 那么我们自然能够通过 Qt 来自行给一个窗口添加子窗口。

QDockWidget 类即是浮动窗口,它一般围绕在中心部件周围。

创建一个浮动窗口

和上面菜单栏工具栏一样,都是直接new 出来一个对象,然后通过 add 函数来添加浮动窗口。

和工具栏一样,浮动窗口可以有多个,因此使用 addDockWidget 来添加浮动窗口。

只不过这里的 addDockWidget 函数必须固定浮动窗口的位置。

以下就是设置浮动窗口位置的宏定义。 

  • Qt::LeftDockWidgetArea : 靠左 
  • Qt::RightDockWidgetArea : 靠右
  • Qt::TopDockWidgetArea : 靠上
  • Qt::BottomDockWidgetArea : 靠下 

 此时的浮动窗口未添加任何控件,因此没有任何功能。

为浮动窗口添加控件

子窗口添加控件有点复杂。

如果只在子窗口中添加一个控件可以直接添加,但是如果想添加多个控件的话,就必须借助 QWidget 了。

这是因为 DockWidget 一次只能包含一个 QWidget,如果想添加多个控件,就必须先添加一个 QWidget 对象,然后往 QWidget 对象中添加一个布局管理器,然后将新的控件添加到布局管理器中,最后连同布局管理器一起放在 QWidget 中。

这样就能够成功设置好想添加到子窗口的控件。

 对话框

在一些窗口的时候,有时候会弹出一些对话框,比如记事本修改文本后退出,会提示是否保存。

这种就是对话框,Qt 也提供了对话框,供我们使用。

在创建项目的时候,base class 选项选则 QDialog 就是一个对话框。

 不过这种方式我们一般不使用,因为对话框一般都是在主窗口弹出的。

比如这样,设置一个按钮,点击按钮即可弹出对话框。

不过这样有个内存泄漏的问题,每一次点击按钮都会创建一个对话框,但是这个对话框却没有delete,虽然我们挂在了对象树上,但问题是,窗口没有关闭,对象树也没有销毁,因此这里需要修改代码。

比如按下对话框的关闭按钮即可释放内存,这样就 Ok 了。

这样的操作 Qt 已经给我们提供了,即通过 setAttribute 函数,给 dialog 设置一个属性,该属性是 

WA_DeleteOnClose, 即关闭的时候自动销毁,这样就不会造成内存泄漏了。

自定义对话框

想要自定义对话框有两种方式:纯代码和图形化界面。

纯代码定义对话框

纯代码方式必须先创建一个 Dialog 类,该类继承自 QDialog 。

首先先新建一个类,该类继承自 QDialog。


 

然后在新建的类的构造函数中添加控件,这里的布局管理器不是必要的,只是为了美观。 

然后在 MainWindow 中给按钮添加槽函数,即点击按钮后显示一个对话框。 

可以看到,对话框中确实新增了按钮和 label。 

 

图形化界面定义对话框

 图形化界面方式定义对话框首先需要新建一个 ui 文件。

由于本次是创建一个 Dialog,因此就选择这三个中的任意一个。 

 这样我们就能在对话框中直接手动添加控件了。

给按钮添加槽函数。

之后在 MainWindo 的ui 文件中添加控件,并且添加槽函数。 

 

可以看到,确实能够显示出一个对话框。 

模态对话框

一般对话框分为两种对话框——模态对话框和非模态对话框。

  • 模态对话框

                出现该对话框时,不能对父窗口进行操作 

  • 非模态对话框

                出现该对话框时,可以对父窗口进行操作

当我们对一个文档进行了修改,退出的时候,一定回弹出一个对话框让我们选则是否保存

 

出现该对话框时,我们无法再对文档进行任何修改,必须做出选择,这就是一种模态对话框。

而如果想要创建一个模态对话框,就需要使用 exec() 函数而非 show() 函数.

这样就制作了一个模态对话框了。 

 

 Qt自带的对话框

有些对话框的使用场景比较经典和常用,针对这些使用场景,Qt 自定义了几种对话框,方便用户使用。

这些对话框都继承自 QDialog ,可以直接使用 QDialog 的 API。

QMessageBox

QMessageBox 自带按钮

QMessageBox 和 QDialog 的创建方式类似,都是通过 new 来开辟控件。

不过不一样的是,QMessageBox 自带图标和按钮,我们可以自行设置,也可以直接采用自带的图标和按钮。

 其中图标有以下图标:无图标、信息图标、警告图标、致命问题图标、操作问题图标等。

 按钮也有以下按钮,有很多种,根据自己需要使用。

 

弹出的对话框如下:

 对于 exec 函数,也就是模态对话框来说,它在执行结束后(对话框关闭)时会返回一个值。

该值是一个 int 类型的数据,该数据即是对话框设置的标准按钮的值。

 可以看到,确实在点击对应按钮后,就会获取到该按钮对应的值。

 通过这种方法我们也能够实现类似 connect 函数的作用,即通过判断返回值来调用函数。

像这种标准的按钮是无法使用信号槽机制的,不过 QMessageBox 也能够自定义按钮。

QMessageBox 自定义按钮

但是在添加自定义按钮的时候,我们能够看到两个参数,一个是按钮的地址,一个是 ButtonRole

 

这个 ButtonRole 指该按钮在对话框中所扮演的角色,我们可以直接查看一下ButtonRole

比如我们设置 ButtonRole 为 AcceptRole 那么点击这个按钮就表示接受的意思,RejectRole 则表示拒绝,HelpRole 表示帮助的角色,自定义的按钮需要设定好所扮演的角色。 

这里我们就随意设置一个接受的角色。 

 快速搭建一个 QMessageBox

QMessageBox 还有一种快速搭建对话框的方式,即通过 QMessageBox::information / warning /critical / question 四种函数来快速搭建。

这四个函数实际上就是 QMessageBox 自带的四种图标的名称,使用对应的函数会自带对应的图标。

四个函数的参数都一样,分别是 父节点、对话框标题、对话框文本、标准按钮,其返回值和exec函数一样,都是按下的按钮的值,可以直接判断使用。 

 这样就能够直接 new 一个图标是 information、带有 ok 和 no 两个按钮的 QMessageBox 对话框

而且通过这种方式创建的对话框都是 模态的。 

 QColorDialog

该对话框实现了一个调色板的功能,类似于画图中的调色板。

这个调色板我们能够做到像 QDialog 和 QMessageBox 一样,通过 new 创建和 delete 删除。

不过 Qt 自己提供了静态函数,类似于 QMessageBox 一样,可以快速创建一个调色板。

QColorDialog::getColor 函数,是 QColorDialog 的一个静态函数。

三个参数分别是 调色板初始颜色、函数的父指针、QColorDialog 的标题。

其中初始颜色是通过 rgb 设置或者直接使用 Qt 自带的宏设置的。

rgb 是三原色的缩写,即红色、绿色和蓝色,通过设置三种颜色的比例来构建其他所有颜色

我们设置通过调色板来设置背景颜色。

 

 这就是 QColorDialog 的作用。

QFileDialog

QFileDialog 是针对于文件的对话框,可以进行保存文件或者打开文件的操作。

它有三种静态函数,分别是 getOpenFileName(获取打开的文件名)、getSaveFileName(获取保存的文件名)、getOpenFileNames(一次打开多个文件)。

 

这三个函数的参数及其类似,分别是父节点的地址、对话框的标题、默认打开的文件路径、以及文件过滤器。

getOpenFileName 和 getOpenFileNames 的作用类似,因此不再赘述,咱们直接试试 getOpenFileName 和 getSaveFileName 两个函数。

设置两个按钮,分别是 getOpenFileName 以及 getSaveFileName 两个函数。

getSabeFileName 右下角是保存 。

 

而getOpenFileName 右下角是打开。 

不过这里的打开和保存按钮并没有效果,因为我们没有给它设定函数,因此没有作用。

QFontDialog

QFontDialog 能够弹出一个修改字体的对话框,和上面的调色板一样,都是通过静态函数进行调整

通过 QFontDialog::getFont 函数能够直接构建一个 QFontDialog 对话框。

该函数有两个参数。

 其中 第一个 ok 函数是一个输入输出型参数,因为设置字体的对话框有两个按钮——ok 和 cancel

如果点击的是 ok,那么该参数的值就会变成 true,cancel 则是 false。

因此这里的参数 ok 初始值应该是 false。

其次,该函数的返回值是一个 QFont,也就是返回在对话框中选择的字体进行返回,用来设置字体

这里的槽函数是获取到字体对话框中的字体,并且将按钮的字体修改为对应的字体。 

可以看到,确实能够设置按钮的字体。 

 

QInputDialog

 这是一个输入对话框,它有三种输入对话框:Int、Double、Item。

分别通过 getInt、getDouble、getItem 三种静态函数创建。

这三个函数的参数都很相似。

getItem/getInt/getDouble : 父节点的指针、对话框的标题、对话框的内容、初始值、最小值、最大值、每次微调的大小、ok值(QFontDialog::getFont的参数含义一样),flags 值。

由于初始值后面的内容后有默认值,因此我们可以不管。 

接着我们来使用一下三个对话框。

可以看到,条目输入框我们需要另外添加一个 QStringList 的参数,该参数类似于C++的 List<String> 类型。

 

 可以看到,三种函数的返回值都是对话框输入的值。

而条目输入框的条目们只是用作一个选择,并不一定需要是条目内容。

总结

本文总结了一个成熟的窗口应该具有的窗口,菜单栏、工具栏、状态栏、浮动窗口、对话框等。

也分别总结了Qt是如何实现它们的,以及各个函数的使用,相信会对大家的Qt学习之旅有所帮助

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值