【快速上手QT】01-QWidgetQMainWindow QT中的窗口

总所周知,QT是一个跨平台的C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,当然我们用到QT就是要做GUI的,所以我们快速上手QT的第一篇博文就讲QT的界面窗口。

我用的IDE是VS2019,使用QTcreator的小伙伴也是可以跟着一起学习的,毕竟QT提供的API都是一样的,就是配置方面会有些许不同。

窗口的选择

我们创建一个QT项目,会让我们选择一个作为我们界面的基类,是从这三个里选:QWidget,QMainWindow,QDialog。默认是给我们选QMainWindow。

QWidget是精简版的窗口,也就是单单一个窗口其他啥也没有。

QMainWindow与QWidget相比,就是可以带菜单栏的QWidget。

QDialog比较不一样,它属于对话框,一般来说主界面不会选择它作为基类去继承它。

QMainWindow和QDialog都是QWidget的子类,也就是说QWidget是一切窗口类的爹。

 下面是基于QMainWindow的界面。

下面是基于QWidget的界面。

下面是基于QDialog的界面。

可以看的出来QWidget就是一个普普通通的界面,而QMainWindow对比QWidget就多了一个工具栏(不是菜单栏)。但是当我把初始化安排上的UI(ui.setupUi(this))删掉之后QMainWindow连那个工具栏也没有了,跟QWidget也没有什么区别。

QDialog的右上角与另外两个不一样,上面两个是常规的最小化,放大,退出。而QDialog变成了一个问号和退出。

一般情况下我们都是选择QWidget和QMainWindow比较多。对我来说,我不喜欢使用QtDesigner也就是图形化UI设计,因此在我这里QWidget和QMainWindow都是一样的,我就是用的默认选择。

QWidget

当我把QtDesigner配置的ui删掉之后可以看到界面变成下面这样了。

因为没有了界面大小的设置,整个窗口挤成一团了。

既然我不使用QtDesigner来布局界面,那么我就需要使用代码来对窗口进行设置了。

学习QT的最好办法就是去查阅QT官方提供的手册,就是在我们安装QT的目录下面就有自带的手册。找不到的小伙伴使劲去找,实在找不到的话还有网页的中文版。

Qt 5.9.9 -中文文档编制,帮助,手册,教程Qt5 / C/C++ / GUI 框架 / 中文文档编制 / 中文帮助 / 中文手册 / 中文教程icon-default.png?t=N7T8http://qt5.digitser.top/5.9/zh-CN/index.htmlQMainWindow的函数有很多,下面的图都还没截完。我们只挑几个常用的(我个人认为的)来讲讲,因为我们是快速上手嘛。

 第一件事,设置大小 

但是我们在QMainWindow拥有的函数中好像并没有找到相关的函数,因此我们需要往它的父类找,也就是QWidget里。因为接下来介绍的函数是属于QWidget的,但是三个窗口基类都可以使用,属于通用的函数。

很快我们就能找到很多相关函数。

void resize(int w, int h)

这个函数就可以修改窗口的大小,当然它还有重载函数,不过我们就先不提。

我们发现我们设置完大小之后仍然可以通过拖拽的方式去修改窗口的大小,我们也可以设置为固定的大小不允许手动修改窗口大小。

void setFixedSize(int w, int h)

除了设定固定的大小,我们还可以单独设置固定长度或是高度,这样子除了固定死的一边之外,剩下一边的大小还是可以通过拖拽来改变。

void setFixedHeight(int h)
void setFixedWidth(int w)

当然,除了通过固定的方法不让用户拖拽,我们还可以用别的办法去限制窗口的大小。

void setMaximumHeight(int maxh)
void setMaximumSize(int maxw, int maxh)
void setMaximumWidth(int maxw)
void setMinimumHeight(int minh)
void setMinimumSize(int minw, int minh)
void setMinimumWidth(int minw)

从上面函数的名字应该可以知道,这些函数可以去设置窗口的最大最小的长和宽,也就是可以把窗口的大小限制在一个范围里,用户可以拖拽窗口来修改大小,但是不能比我们设置的最小大小更小,也不能比我们设置的最大大小更大。

第二件事,起个名字

void setWindowTitle(const QString &)

使用上面的函数我们直接给一个字符串就可以修改窗口的名称了。

但是我们发现,我们的中文的乱码的,这是编码格式的问题,因此在QT中如果我们使用到了中文,那么都按照下面的格式去使用,不需要去记,我们直接用就行。

QString::fromLocal8Bit("折途");

这样就没问题了。

除了设置名字以外,我们还可以修改窗口左上角的小图标。

void setWindowIcon(const QIcon &icon)

这个函数我们需要传入一个QIcon类型的变量,我们先不管那么多,就按照我上面的写法,直接马上弄一个QIcon,传入的参数就是图片的路径。

当然我上面的写法不规范,一般在QT中我们使用图片资源之类的我们有其他方法,很少这样直接使用文件路径来写的,这个之后的文章中会说。

开启关闭

这时候我们常用的基础设置基本上就上面这些,我们再回过头看看main函数。

可以看得出来创建工程的时候,默认是帮我们把main函数写好了。

主要我们看看帮我们创建的我们主界面的类,它还帮我们调用了show这个函数。

当我们把使用show这行代码删掉之后我们能发现我们的界面不会像之前那样自己弹出来了,并且程序也没有退出,仍然在执行。

那么我们可以判断出show函数就是让我们的界面出现的。

void show()

而有显示也就有退出。

bool close()

我们在主函数中show函数的后面加上close函数,我们就能发现窗口弹出后很快就又消失了。实际上当主窗体使用了close之后应该是退出整个程序的,但是我们发现窗口消失之后程序并没有结束。这是因为我们写在了main函数里,在执行完close之后我们卡在了a.exec()中。只有我们已经卡在了a.exec()中的时候我们再调用close才会使得程序退出,这一点如何实现我们有很多办法,在后续的文章中会提到。

那如果我们想要页面消失但是又不想程序退出那该怎么办呢?

void hide()

调用上面的函数我们会将当前窗口隐藏,但是不会退出程序,而我们再次调用show时窗口又会出来。

QMainWindow

上面讲了一些通用的函数,那么接下来就讲一讲QMainWindow特有的函数了。

我们知道QMainWindow就是比QWidget多了个菜单栏,那么我们就先说说QMainWindow如何添加菜单栏。

QMenuBar菜单栏

凭借我高超的英语水平(四级差122分),一眼就能找出如何给我们的QMainWindow添加一个菜单栏。

void setMenuBar(QMenuBar *menuBar)

但是要添加菜单栏,我们首先需要有菜单栏,需要传入的参数是QMenuBar类型的变量指针。

这时候我们可以在QT官方手册里再去搜索QMenuBar。

可以看出我们要构造一个QMenuBar出来,只需要传递一个QWidget*类型的参数即可,这个我们只需要填入this即可(需要在我们主界面的成员函数中创建才可以使用this)。

至于为什么就涉及到QT的机制了。简单来说就是给QMenuBar认个“义父”,构造函数的形参名字也叫parent嘛。参数填入this就可以认为我们把这个QMenuBar挂载在了我们的主界面上,当主界面被关闭之后(调用了析构函数),会自动释放“义子们”的资源,也就是说我们new了一个QMenuBar,但是我们不需要手动去释放资源,这也是QT方便的地方。

那么我们可以创建一个QMenuBar的对象,然后添加进我们的主界面里。

但是我们却发现界面里并没有菜单栏,这是不是我们代码写错了呢。

其实菜单栏已经有了,只是我们看不到而已,因为菜单栏是空的。

菜单栏自然是有菜单的,所以我们还需要给菜单栏添加菜单。

QMenu菜单

凭借我高超的英语水平(四级差122分),一眼就能找出如何给我们的QMenuBar添加一个菜单。

QAction *addMenu(QMenu *menu)
QMenu *addMenu(const QString &title)
QMenu *addMenu(const QIcon &icon, const QString &title)

有三个重载版本,我们接下来把三种全试一遍。

第二个还好说,只要传入字符串即可,但是第一种的QMenu和第三种的QIcon又是什么鬼。

我们一个个看,人家要QMenu我们就创建一个QMenu嘛,反正我们有QT官方提供的手册,搜索一下就OK啦。

我们在QMenu的构造函数中就可以直接给出QMenu上面的文字,也可以后续通过调用它的成员函数去设置。那么获取QMenu的问题就算搞定了。

那么QIcon其实也是一样的。

它的构造函数比较多,我们就使用我们上面用过的,直接传入图片的路径就行。

那么接下来我们就为我们的菜单栏去添加菜单吧。

#include "ZheTu.h"


ZheTu::ZheTu(QWidget *parent): QMainWindow(parent){
    this->setFixedSize(1000,1000);
    this->setWindowTitle(QString::fromLocal8Bit("折途"));
    this->setWindowIcon(QIcon("./zhetu.ico"));

    QMenuBar* mb = new QMenuBar(this);
    this->setMenuBar(mb);

    mb->addMenu("one");

    QMenu* m2 = new QMenu("two", this);
    mb->addMenu(m2);

    mb->addMenu(QIcon("./zhetu.ico"), "three");

}

ZheTu::~ZheTu()
{}

这样我们就可以看到菜单栏了,并且菜单栏里也有了菜单。

但是我们注意到第三个菜单只能看到icon图标而看不到文字了,这个搞起来挺麻烦的,我查了好久也没有找到比较简单的方法,那么我们就尽量避免在菜单栏中添加带图片的菜单吧。

有了菜单之后菜单也空荡荡的,我们可以给菜单添加菜单项。

QAction菜单项

凭借我高超的英语水平(四级差122分),一眼就能找出如何给我们的QMenu添加一个菜单项。

可以看出有八个重载版本,我们应该选哪一个呢,一般情况下我们都不选,我们选择它父亲(父类)的函数,也就是QWidget的函数,没错,QMenu也继承了QWidget。

为了使用上面这一种重载版本,我们需要创建一个QAction出来,我们照例是在Qt助手里搜索。

有三种构造函数,我们都来试一试。

#include "ZheTu.h"

ZheTu::ZheTu(QWidget *parent): QMainWindow(parent){
    this->setFixedSize(1000,1000);
    this->setWindowTitle(QString::fromLocal8Bit("折途"));
    this->setWindowIcon(QIcon("./zhetu.ico"));

    QMenuBar* mb = new QMenuBar(this);
    this->setMenuBar(mb);

    QMenu* m1 = new QMenu("one", mb);
    mb->addMenu(m1);
    
    QMenu* m2 = new QMenu("two", mb);
    mb->addMenu(m2);
    
    QAction* a1 = new QAction(m2);
    QAction* a2 = new QAction("a2", m2);
    QAction* a3 = new QAction(QIcon("./zhetu.ico"), "a3", m2);
    m2->addAction(a1);
    m2->addAction(a2);
    m2->addAction(a3);
}

可以看得出我们确实是添加了三个菜单项出来了,第一个没有指定文本,因此是空白的,前两个没有指定icon,因此在图标的位置上是空着的。

我是用的VS2019敲的QT,人家VS的菜单栏中的菜单项里还有选项就像下图一样,这个是怎么做的呢。

实际上QMenu也可以添加QMenu,也就是说我们除了给 QMenu添加QAction以外,添加QMenu也是可以套娃的。

#include "ZheTu.h"

ZheTu::ZheTu(QWidget *parent): QMainWindow(parent){
    this->setFixedSize(1000,1000);
    this->setWindowTitle(QString::fromLocal8Bit("折途"));
    this->setWindowIcon(QIcon("./zhetu.ico"));

    QMenuBar* mb = new QMenuBar(this);
    this->setMenuBar(mb);

    QMenu* m1 = new QMenu("one", mb);
    mb->addMenu(m1);
    
    QMenu* m2 = new QMenu("two", mb);
    //mb->addMenu(m2);
    m1->addMenu(m2);
    

    QAction* a1 = new QAction(m2);
    QAction* a2 = new QAction("a2", m2);
    QAction* a3 = new QAction(QIcon("./zhetu.ico"), "a3", m2);
    m2->addAction(a1);
    m2->addAction(a2);
    m2->addAction(a3);
}

其他部件

在我们QMainWindow中,我们可以拥有一个菜单栏,一个状态栏,一个中心部件,多个工具栏和多个铆接部件。

添加的函数分别是

void setMenuBar(QMenuBar *menuBar);
void setStatusBar(QStatusBar *statusbar);
void setCentralWidget(QWidget *widget);
void addToolBar(QToolBar *toolbar);
void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget);

其实从名字我们也可以看的出来哪些是只能有一个的,哪些是可以有多个的。只能有一个的部件那么函数开头是set,而可以有多个的部件函数开头是add。

中心部件就是指定一个其他部件作为中心,比如说我要自己写一个VS出来,那么敲代码的部分就是中心对吧,那么我就可以把敲代码存放文本的部件设置为中心部件,不过实际上我不设置也可以,只要布局的合理就行,所以这里不介绍添加中心部件。

铆接部件是整一个区域出来,我们可以拖动它放到其他地方,但实际上也没什么卵用所以也不介绍了,可以参考前阵子力扣更新的自定义界面功能。

工具栏可以有多个,这个用的比较多,但是很简单,就当它是可以有多个并且可以自己拖动到其他位置(不一定在顶上)的菜单栏就行,给工具栏也是添加QAction的,比菜单栏就多了个可以停靠在其他位置(左边,右边,下面。。。),所以很简单,这里也不介绍了。

QStatusBar状态栏

状态栏只能有一个,它的函数不多,就下面几个。

我们就记住两个就行。

void addPermanentWidget(QWidget *widget, int stretch = 0);
void addWidget(QWidget *widget, int stretch = 0);

我们的状态栏是在界面的最下面的,第一个函数会把添加的QWidget*类型的参数添加到状态栏的右侧,也就是界面的右下方。第二个函数会添加到左侧,也就是界面的左下方。

那么我们需要创建一个QWidget对象吗,它不是一个界面吗,怎么塞得进一个状态栏里。

这里有点超纲了,我们就记住对于状态栏,我们一般给它塞的参数是QLabel类型的,这是一个标签类,他的父类的父类是QWidget,所以我们实际上使用了多态。

具体的我以后的文章会讲,这里看看我下面的用法就行。

#include "ZheTu.h"

#include <QLabel> 

ZheTu::ZheTu(QWidget *parent): QMainWindow(parent){
    this->setFixedSize(1000,1000);
    this->setWindowTitle(QString::fromLocal8Bit("折途"));
    this->setWindowIcon(QIcon("./zhetu.ico"));

    QStatusBar* sb = new QStatusBar(this);
    this->setStatusBar(sb);

    QLabel* l1 = new QLabel("this is left", this);
    sb->addWidget(l1);
    QLabel* l2 = new QLabel("this is right", this);
    sb->addPermanentWidget(l2);

}

结尾

那么这篇文章就简单介绍了QT中的窗口,QWidget和QMainWindow,主要是讲了菜单栏。

但是我们实际上还有最重要的部分没说,那就是虽然我有了菜单也有了选项,但是我按了选项没有任何反应啊。

这个就涉及到了QT的精髓,信号和槽函数了,后面的文章我会进行讲解,今天就简简单单的了解一下QT的窗口界面就好啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/371121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

神经网络 | 基于 CNN 模型实现土壤湿度预测

Hi&#xff0c;大家好&#xff0c;我是半亩花海。在现代农业和环境监测中&#xff0c;了解土壤湿度的变化对于作物生长和水资源管理至关重要。通过深度学习技术&#xff0c;特别是卷积神经网络&#xff0c;我们可以利用过去的土壤湿度数据来预测未来的湿度趋势。本文将使用 Pad…

Postgresql体系结构

client连接PostgreSQL过程&#xff1a; 1、客户端发起请求 2、主服务postmaster进程负责服务器是否接受客户端的host通信认证&#xff0c;服务器对客户端进行身份鉴别 3、主服务进程为该客户端单独fork一个客户端工作进程postgres 4、客户端与postgres进程建立通信连接&#xf…

【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录 一、647、回文子串二、516、最长回文子序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、647、回文子串 思路分析&#xff1a;判断一个字符串是否为回文串那么必须确定回文串的所在区间&#xff0c;而一维…

SQL--DDL

全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了 一套操作关系型数据库统一标准。 1 SQL通用语法 在学习具体的SQL语句之前&#xff0c;先来了解一下SQL语言的同于语法。 1). SQL语句可以单行或多行书写&#xff0…

处理SERVLET中的错误和异常

处理SERVLET中的错误和异常 应用服务器服务客户机请求时可能会遇到一些问题,如找不到所请求的资源或运行中的servlet引发异常。例如,在线购物门户中如果用户选择了当前缺货的物品要放入购物车中,就会出现问题, 这种情况下,浏览器窗口中将显示错误消息。您可以在servlet中…

Maven工程的配置及使用

一、Maven章节 Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具 1.1、maven的作用 1&#xff09;依赖管理&#xff1a; 方便快捷的管理项目依赖的资源包&#xff08;jar包&#xff09;避免版本冲突 2&#xff09;统一项目结构&…

STC系列单片机的中断系统

目录 一、中断系统的定义 二、STC15系列单片机的中断请求源及结构图 三、中断查询表以及触发方式 四、在keil c中如何声明中断函数 五、外部中断 六、基于STC15芯片实战中断系统的使用 &#xff08;1&#xff09;外部中断2/外部中断3来检测门的开关状态 &#xff08;2&a…

【C++】- 继承(继承定义!!基本格式!切片概念!!菱形继承详解!)

继承 了解继承继承的定义基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承和友元菱形继承和菱形虚拟继承 了解继承 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保 持原有类特性的基础上进行扩展&#xff0c;增加功能&a…

优化 IT 支出和消除浪费的 8 种主要方法

不懈追求最佳 IT 支出对于任何组织的长期可持续发展和成功都至关重要。在这个技术快速进步的时代&#xff0c;您必须做出明智的决策&#xff0c;消除浪费&#xff0c;同时最大限度地提高技术投资的价值。 从进行 IT 成本分析到采用敏捷预算和技术标准化&#xff0c;这些策略对…

关于服务器解析A记录和CNAME记录的分析

内容提要: 大致讲下理解,dns域名解析这一块 0 . 问题来源 最近搞了一个七牛云上传,然后需要配置融合cdn加速,也就是可以加速域名,中间有一部需要CNAME 域名,也就是将七牛云提供的域名CNAME一下,查阅资料其实就是起一个别名,好访问而已. 方便我们访问云存储,达到加速的效果. …

Elasticsearch(ES) 简述请求操作索引下文档 增删查改操作

上文 Elasticsearch(ES) 创建带有分词器规则的索引 带着大家创建了一个带有分词功能的索引 老规矩 我们启动一下ES服务 本文 我们就来说说 关于文档的操作 我们先来添加一个文档 就像数据库加一条数据一样 这里 并不需要指定什么表结构和数据结构 它的文档结构是无模式的 添…

es6中标签模板

之所以写这篇文章&#xff0c;是因为标签模板是一个很容易让人忽略的知识点 首先我们已经非常熟悉模板字符串的使用方法 const name "诸葛亮" const templateString hello, My name is ${name}标签模板介绍 这里的标签模板其实不是模板&#xff0c;而是函数调用…

2024年Java面试题大全 面试题附答案详解,BTA内部面试题

基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象&#xff08;Java最重要的特性&#xff0c;让程序耦合度更低&#xff0c;内聚性更高&#xff09; 阿里内部资料 基本类型 大小&#xff08;字节&#xff09; 默认值 封装类 6、Java自动装箱与拆箱 装箱就是…

《幻兽帕鲁》解锁基地和工作帕鲁数量上限

帕鲁私服的游戏参数通常可通过配置文件 PalWorldSettings.ini 来进行修改&#xff0c;然而这个配置文件有个别参数对游戏不生效&#xff0c;让人很是头疼。没错&#xff01;我说的就是终端最大的帕鲁数量&#xff01; 其实还有另外一种更加高级的参数修改方式&#xff0c;那就…

《Python 网络爬虫简易速速上手小册》第2章:网络爬虫准备工作(2024 最新版)

文章目录 2.1 选择合适的爬虫工具和库2.1.1 重点基础知识讲解2.1.2 重点案例&#xff1a;使用 Scrapy 抓取电商网站2.1.3 拓展案例 1&#xff1a;使用 Requests 和 BeautifulSoup 抓取博客文章2.1.4 拓展案例 2&#xff1a;使用 Selenium 抓取动态内容 2.2 设置开发环境2.2.1 重…

【前沿技术杂谈:开源软件】引领技术创新与商业模式的革命

【前沿技术杂谈&#xff1a;开源软件】引领技术创新与商业模式的革命 开源软件如何推动技术创新开源软件的开放性和协作精神促进知识共享和技术迭代推动关键技术的发展开源软件与新技术的融合 开源软件的商业模式开源软件的商业模式将开源软件与商业软件相结合 开源软件的安全风…

Docker Dockerfile

1、概念介绍 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 指令按照从上到下&#xff0c;顺序执行 #表示注释 每条指令都会创建一个新的镜像层并对镜像进…

PyTorch 2.2 中文官方教程(十)

使用整体追踪分析的追踪差异 原文&#xff1a;pytorch.org/tutorials/beginner/hta_trace_diff_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者: Anupam Bhatnagar 有时&#xff0c;用户需要识别由代码更改导致的 PyTorch 操作符和 CUDA 内核的变化…

vulhub中AppWeb认证绕过漏洞(CVE-2018-8715)

AppWeb是Embedthis Software LLC公司负责开发维护的一个基于GPL开源协议的嵌入式Web Server。他使用C/C来编写&#xff0c;能够运行在几乎先进所有流行的操作系统上。当然他最主要的应用场景还是为嵌入式设备提供Web Application容器。 AppWeb可以进行认证配置&#xff0c;其认…

【数据结构]排序算法之插入排序、希尔排序和选择排序

简单不先于复杂&#xff0c;而是在复杂之后。 文章目录 1. 排序的概念及其运用1.1 排序的概念1.2 排序运用1.3 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 基本思想2.1.2 直接插入排序2.1.3 希尔排序&#xff08;缩小增量排序&#xff09; 2.2. 选择排序2.2.1 基本…