Qt 窗口的尺寸

本文通过多个案例,详细说明关于Qt窗体尺寸的一些重要问题

默认尺寸

对于一个Qt的窗口(继承于QWidget),获取其窗体尺寸的方法size();

以一个Qt创建Qt Widgets Application项目的默认生成代码为基础,做如下测试

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{qDebug()<<"MainWindow::MainWindow:"<<this->size();this->resize(1200,800);qDebug()<<"MainWindow::MainWindow:"<<this->size();
}

第一个this->size()输出QSize(640, 480),即MainWindow具有默认的尺寸640*480

第二个this->size()输出QSize(1200, 800)

实际上,继承于QWidget的控件,例如QPushButton,QLineEdit等也会获得默认的尺寸640*480

    QWidget* page=new QWidget;qDebug()<<".."<<page->size();QPushButton* btn=new QPushButton;qDebug()<<".."<<btn->size();QLineEdit* edt=new QLineEdit;qDebug()<<".."<<edt->size();

以上输出都是QSize(640, 480)

布局之后的尺寸
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{qDebug()<<"MainWindow::MainWindow:"<<this->size();this->resize(1200,800);QWidget* page=new QWidget;qDebug()<<".."<<page->size();QVBoxLayout* layout=new QVBoxLayout(page);QPushButton* btn=new QPushButton;qDebug()<<".."<<btn->size();QLineEdit* edt=new QLineEdit;qDebug()<<".."<<edt->size();layout->addWidget(btn);layout->addWidget(edt);this->setCentralWidget(page);qDebug()<<".."<<page->size();qDebug()<<".."<<btn->size();qDebug()<<".."<<edt->size();qDebug()<<"MainWindow::MainWindow:"<<this->size();//当界面显示出来之后,点击按钮查看控件尺寸connect(btn,&QPushButton::clicked,[=]{qDebug()<<".."<<page->size();qDebug()<<".."<<btn->size();qDebug()<<".."<<edt->size();});
}

以上代码this->setCentralWidget(page);之后的三个打印对应的尺寸应该是多少?

依然还是 QSize(640, 480)

而connect()方法中的三个打印对应的值则分别为

.. QSize(1200, 800)
.. QSize(1178, 28)
.. QSize(1178, 24)

以上代码说明两个问题:

(1)将控件加入到布局,然后放入了父窗体中,则控件的尺寸会根据父窗体的布局重新设置

(2)控件尺寸的重新设置发生在窗体显示出来后(绘制时)

 固定尺寸

 以下代码实现在主窗体上布局多个按钮和子窗体,实现点击按钮切换每个子窗体的隐藏和可见。

但是存在问题:

(1)4个子窗体平分了主窗体的尺寸;

(2)隐藏一个子窗体后,其他的子窗体尺寸被更改(窗体重绘时会重新设置尺寸)

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{qDebug()<<"MainWindow::MainWindow:"<<this->size();this->resize(1200,800);QWidget* page=new QWidget;QVBoxLayout* layout=new QVBoxLayout(page);QScrollArea* contentArea=new QScrollArea;contentArea->setWidgetResizable(true);contentArea->setWidget(page);for(int i=0;i<4;i++){QWidget* p=new QWidget;//设置窗体背景色,使得区分背景,可见p->setStyleSheet("background-color:green");QPushButton* b=new QPushButton;layout->addWidget(b);layout->addWidget(p);connect(b,&QPushButton::clicked,[p]{//点击按钮后窗体切换显示和隐藏效果p->setVisible(!p->isVisible());});}this->setCentralWidget(contentArea);
}

如果需要设置子窗体在重绘时不改变尺寸,那么需要设置其尺寸

例如在QWidget* p=new QWidget;下方增加 p->setFixedHeight(300);

这样隐藏和显示一个子窗体不会对任意其他的子窗体的尺寸造成影响。

更改后会发现,当隐藏完所有的子窗体后,所有的按钮被均匀布局在了主窗体,如果想要的效果是按钮从主窗体从上往下紧密排列,可以在layout添加完所有的控件和窗口后,添加一个stretch,即在this->setCentralWidget(contentArea);上一行添加layout->addStretch();

窗体实际尺寸

如果MainWindow设置的高度为600,而它的中心窗体高度为800,该怎样显示?

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{qDebug()<<"MainWindow::MainWindow:"<<this->size();this->resize(800,600);qDebug()<<"MainWindow::MainWindow:"<<this->size();//默认情况下MainWindow没有centralWidgetQWidget* center=new QWidget;qDebug()<<"center:"<<center->size();QVBoxLayout* layout=new QVBoxLayout(center);QWidget* page1=new QWidget;page1->setStyleSheet("background-color:green");page1->setFixedHeight(400);QWidget* page2=new QWidget;page2->setFixedHeight(400);page2->setStyleSheet("background-color:yellow");layout->addWidget(page1);layout->addWidget(page2);qDebug()<<"center:"<<center->size();this->setCentralWidget(center);//此时输出QSize(800, 600)qDebug()<<"MainWindow::MainWindow:"<<this->size();
}
int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();qDebug()<<"w size:"<<w.size();return a.exec();
}

以上代码执行时,MainWindow构造函数中的输出mainwindow的窗体高度为600,但是在窗口显示(执行了w.show())之后,它的高度却是829

给窗体设置某个尺寸,实际显示的时候窗体根据布局,不一定恰好按照给定的尺寸来显示

尺寸不够引起重叠的窗体

如果主窗体设置了固定高度600,而它的中心窗体设置固定高度1200?

此时,肯定主窗体显示不全page1和page2

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{qDebug()<<"MainWindow::MainWindow:"<<this->size();this->resize(800,600);this->setFixedHeight(600);qDebug()<<"MainWindow::MainWindow:"<<this->size();//默认情况下MainWindow没有centralWidgetQWidget* center=new QWidget;center->resize(800,500);qDebug()<<"center:"<<center->size();QVBoxLayout* layout=new QVBoxLayout(center);QWidget* page1=new QWidget;page1->setStyleSheet("background-color:green");page1->setFixedHeight(600);QWidget* page2=new QWidget;page2->setFixedHeight(600);page2->setStyleSheet("background-color:yellow");layout->addWidget(page1);layout->addWidget(page2);qDebug()<<"center:"<<center->size();this->setCentralWidget(center);//此时输出QSize(800, 600)qDebug()<<"MainWindow::MainWindow:"<<this->size();QTimer::singleShot(1000,[=](){//为什么page1和page2的高度是600,而实际显示的界面没有600?//事实上page1和page2的高度都是600,界面上也是600,但是page1和page2重叠了一部分qDebug()<<"page1:"<<page1->size();qDebug()<<"page2:"<<page2->size();qDebug()<<"center:"<<center->size();qDebug()<<"sizeHint:"<<layout->sizeHint();qDebug()<<"MainWindow::MainWindow:"<<this->size();});
}

这里输出了layout的sizeHit(),为1229,layout上放置了page1和page2,他们的高度600+600=1200,29是布局周边留下的空白部分。

最小高度限制

这里展示了一个实际项目中遇到的问题,需要在一个页面中放置多个表格,并且每个表格要直接显示至少5行,更多行的时候滚动条显示。

以下代码是从项目中抽取的问题特征部分:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{this->resize(800,600);QWidget* page=new QWidget;QVBoxLayout* layout=new QVBoxLayout(page);QScrollArea* contentArea=new QScrollArea;contentArea->setWidgetResizable(true);contentArea->setWidget(page);for(int i=0;i<4;i++){TableWidget* p=new TableWidget;QPushButton* b=new QPushButton;layout->addWidget(b);layout->addWidget(p);connect(b,&QPushButton::clicked,[p]{//点击按钮后窗体切换显示和隐藏效果p->setVisible(!p->isVisible());qDebug()<<"p size:"<<p->size();});}layout->addStretch();this->setCentralWidget(contentArea);
}

 TableWidget只是一个平凡的QTableWidget实例,它设置了默认表格有6行8列,

TableWidget::TableWidget()
{this->setRowCount(6);this->setColumnCount(8);
}

上述代码的效果:

目前的问题是每个表格高度都被挤压了,只显示了一行。

一种解决问题的思路是,在表格初始化时,设置最小高度限制:

TableWidget::TableWidget()
{this->setMinimumHeight(250);this->setRowCount(6);this->setColumnCount(8);
}

 一个更复杂的示例

以下是一个更复杂一些的示例,这个示例有助于理解Qt在布局控件的过程中对尺寸的更改。

代码目的是在主界面上加载多个Drawer页面,Drawer页面是一种类似抽屉的盒子,可以打开关闭(显示隐藏)

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{this->resize(800,600);QWidget* page=new QWidget;page->setMinimumHeight(1000);//layout用来装载drawerQVBoxLayout* layout=new QVBoxLayout(page);Drawer* d1=new Drawer;Drawer* d2=new Drawer;Drawer* d3=new Drawer;Drawer* d4=new Drawer;QList<Drawer*> drawers{d1,d2,d3,d4};for(int i=0;i<1;i++){QVBoxLayout* lay=new QVBoxLayout;lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addStretch();drawers.at(i)->setContentLayout(lay);}for(int i=1;i<4;i++){QVBoxLayout* lay=new QVBoxLayout;lay->addWidget(new TableWidget);drawers.at(i)->setContentLayout(lay);}//以下的stretch使得drawer可以往页面上面顶for(int i=0;i<4;i++)layout->addWidget(drawers.at(i));layout->addStretch();QScrollArea* contentArea=new QScrollArea;contentArea->setWidgetResizable(true);contentArea->setWidget(page);this->setCentralWidget(contentArea);QTimer::singleShot(1000,[=](){qDebug()<<"MainWindow::MainWindow:"<<this->size()<<","<<this->sizeHint();qDebug()<<"d2:size:"<<d2->size()<<","<<d2->sizeHint();});}

 Drawer提供一个按钮,用于交互显示隐藏页面,和一个接口用于设置页面显示的内容(设置一个布局)

Drawer::Drawer(QWidget *parent): QWidget{parent}
{QVBoxLayout* layout=new QVBoxLayout;layout->addSpacing(0);layout->setContentsMargins(0,0,0,0);QToolButton* btn=new QToolButton;layout->addWidget(btn);area=new QScrollArea;area->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);layout->addWidget(area);this->setLayout(layout);connect(btn,&QToolButton::clicked,[=]{area->setVisible(!area->isVisible());qDebug()<<"drawer size:"<<this->size()<<this->minimumHeight();
//        if(!area->isVisible())
//        {
//            this->setFixedHeight(30);
//        }
//        else
//        {
//            this->setFixedHeight(minHeight);
//        }});
}void Drawer::setContentLayout(QLayout *lay)
{area->setLayout(lay);
//    minHeight=this->minimumHeight();
}

 其中TableWidget依然是QTableWidget的简单实例

TableWidget::TableWidget()
{this->setRowCount(6);this->setColumnCount(8);
}

以上代码的效果如下:

存在的问题是:

(1)表格默认只展示了两行,

(2)并且关闭了一个Drawer后,其他Drawer的尺寸会发生变化

其中,前面对(2)问题的处理是设置固定的尺寸p->setFixedHeight(300);

对应这里就是在Drawer的构造函数第一行加 this->setFixedHeight(300);但是这样一来,会发现每个Drawer之间重叠了,就是尺寸不够引起了窗体重叠,300*400=1200>1000,主窗体中的滚动区域的窗体设置的最小高度1000.

另外隐藏所有的Drawer页面后,剩余的按钮又均匀分布在了主界面。

这里的效果和前面固定尺寸一节遇到的问题看似相同,而实际上却不一样,前面的问题通过在布局的最后增加stretch解决,这里显然不能。

这里遇到的问题是由于按钮点击后隐藏的不是整个Drawer,而只是Drawer中的area,Drawer依然是可见的,因此处于整个主界面的布局之中。这里当Drawer中的area被隐藏后,Drawer页面本身被重新布局了,即只有一个QToolButton参与了布局,所以能看到按钮被布局在了Drawer的中央。

那么,这种情况下该怎样实现效果:

(1)隐藏所有的Drawer的area后,只剩下按钮顶格显示在主页面

(2)表格默认显示至少5行

(3)隐藏一个Drawer不会对其他的Drawer尺寸产生影响

一种方式是要在Drawer显示隐藏切换的时候同时设置固定的尺寸;这个固定的尺寸要使得表格至少显示5行

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{this->resize(800,600);QWidget* page=new QWidget;//给page设置了最小高度后,每个drawer的高度会高一些page->setMinimumHeight(1200);//layout用来装载drawerQVBoxLayout* layout=new QVBoxLayout(page);Drawer* d1=new Drawer;Drawer* d2=new Drawer;Drawer* d3=new Drawer;Drawer* d4=new Drawer;QList<Drawer*> drawers{d1,d2,d3,d4};for(int i=0;i<1;i++){QVBoxLayout* lay=new QVBoxLayout;lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addWidget(new QLineEdit);lay->addStretch();//需要提前设置Drawer的最小高度drawers.at(i)->setMinimumHeight(200);drawers.at(i)->setContentLayout(lay);}for(int i=1;i<4;i++){QVBoxLayout* lay=new QVBoxLayout;lay->addWidget(new TableWidget);//需要提前设置Drawer的最小高度drawers.at(i)->setMinimumHeight(300);drawers.at(i)->setContentLayout(lay);}//以下的stretch使得drawer可以往页面上面顶for(int i=0;i<4;i++)layout->addWidget(drawers.at(i));layout->addStretch();QScrollArea* contentArea=new QScrollArea;contentArea->setWidgetResizable(true);contentArea->setWidget(page);this->setCentralWidget(contentArea);QTimer::singleShot(1000,[=](){qDebug()<<"MainWindow::MainWindow:"<<this->size()<<","<<this->sizeHint();qDebug()<<"d2:size:"<<d2->size()<<","<<d2->sizeHint();});}
TableWidget::TableWidget()
{this->setRowCount(6);this->setColumnCount(8);
}
Drawer::Drawer(QWidget *parent): QWidget{parent}
{QVBoxLayout* layout=new QVBoxLayout;layout->addSpacing(0);layout->setContentsMargins(0,0,0,0);QToolButton* btn=new QToolButton;layout->addWidget(btn);area=new QScrollArea;area->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);layout->addWidget(area);this->setLayout(layout);connect(btn,&QToolButton::clicked,[=]{area->setVisible(!area->isVisible());qDebug()<<"drawer size:"<<this->size()<<this->minimumHeight();//这里根据area显示和隐藏的状态动态调整整个drawer的高度if(!area->isVisible()){this->setFixedHeight(30);}else{this->setFixedHeight(minHeight);}});
}void Drawer::setContentLayout(QLayout *lay)
{area->setLayout(lay);//这里将预设的最小高度记录下来,用于在area显示隐藏切换时设置drawer的高度minHeight=this->minimumHeight();
}

以上代码的效果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HugeGraph Hubble 配置 https 协议的操作步骤

背景 HugeGraph 图数据库的 Server 端支持 https 配置&#xff0c;官方文档中有说明相对比较容易&#xff0c;而 Hubble 部署过程都是 http的。 我们有一个应用要嵌入 hubble 页面&#xff0c;而且部署为 https &#xff0c;那么 Hubble 是否支持配置 https 呢&#xff1f;网…

Docusaurus 搭建站点不完全指南

介绍 它是什么&#xff1f; Docusaurus 是一个基于 React 构建的帮助快速生成静态网站的工具&#xff0c;支持将 MDX 格式编写的文档生成静态 HTML 文件&#xff0c;同时还支持在 Markdown 中嵌入 React 组件。 什么情况下你能用到它&#xff1f; 使用 markdown 语法书写静态博…

Leetcode—80.删除有序数组中的重复项II【中等】

2023每日刷题&#xff08;十&#xff09; Leetcode—80.删除有序数组中的重复项II 双指针实现代码 int removeDuplicates(int* nums, int numsSize){int i 0;int j 1;int k 1;int tmp nums[i];while(j < numsSize) {if(nums[j] tmp && k < 2) {nums[i] n…

【Java】电子病历编辑器源码(云端SaaS服务)

电子病历编辑器极具灵活性&#xff0c;它既可嵌入到医院HIS系统中&#xff0c;作为内置编辑工具供多个模块使用&#xff0c;也可以独立拿出来&#xff0c;与第三方业务厂商展开合作&#xff0c;为他们提供病历书写功能&#xff0c;充分发挥编辑器的功能。 电子病历基于云端SaaS…

【Note详细图解】中缀表达式如何转为后缀表达式?数据结构

中缀表达式 中缀表达式&#xff08;中缀记法&#xff09;是一个通用的算术或逻辑公式表示方法&#xff0c;操作符是以中缀形式处于操作数的中间&#xff08;例&#xff1a;3 4&#xff09;&#xff0c;中缀表达式是人们常用的算术表示方法。 前缀或后缀记法不同的是&#xf…

CentOS 编译安装TinyXml2

安装 TinyXml2 Git 源码下载地址:https://github.com/leethomason/tinyxml2 步骤1&#xff1a;首先&#xff0c;你需要下载tinyxml2的源代码。你可以从Github或者源代码官方网站下载。并上传至/usr/local/source_code/ 步骤2&#xff1a;下载完成后&#xff0c;需要将源代码解…

Spring Boot中RedisTemplate的使用

当前Spring Boot的版本为2.7.6&#xff0c;在使用RedisTemplate之前我们需要在pom.xml中引入下述依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><vers…

nginx浏览器缓存和上流缓存expires指令_nginx配置HTTPS

1.nginx控制浏览器缓存是针对于静态资源[js,css,图片等] 1.1 expires指令 location /static {alias/home/imooc;#设置浏览器缓存10s过期expires 10s;#设置浏览器缓存时间晚上22:30分过期expires @22h30m;#设置浏览器缓存1小时候过期expires -1h;#设置浏览器不缓存expires …

windows 离线安装 vue 环境

由于公司要求在内网开发项目&#xff0c;而内网不能连接外网&#xff0c;因此只能离线安装 vue 环境&#xff0c;在网上找过很多的离线安装方法&#xff0c;但都没有成功&#xff0c;于是在不断的尝试中找到了以下方法。 1、找一台与内网电脑相同系统的有网电脑。 2、在有网的电…

【OpenCV实现图像的几何变换】

文章目录 概要&#xff1a;OpenCV实现图像的几何变换、图像阈值和平滑图像变换小结 概要&#xff1a;OpenCV实现图像的几何变换、图像阈值和平滑图像 使用OpenCV库进行图像处理的三个重要主题&#xff1a;几何变换、图像阈值处理以及图像平滑。在几何变换部分&#xff0c;详细…

uniapp vue2、vue3 页面模板代码块设置

本文分享 uniapp vue2、vue3 页面模板代码块设置 设置路径 HBuilder X -> 工具 -> 代码块设置 -> vue代码块 -> 自定义代码块 如上图操作后在打开的 vue.json 文件的右侧“自定义代码块”中复制如下代码&#xff08;可全选替换也可添加到代码中&#xff09; 示…

vue+iView 动态侧边栏菜单保持高亮选中

iview 组件在使用过程中&#xff0c;多多少少有一些小坑&#xff0c;本文简单罗列一二&#xff1a; 避坑指南&#xff1a; 关于iview 侧边栏菜单未能展开高亮选中回显问题 应用场景&#xff1a;iview-admin下接入动态菜单后&#xff0c;刷新或链接跳入时回显失效 简单就是两个方…

Jenkins 重新定义 pom 内容,打包

文章目录 源码管理构建 源码管理 添加仓库地址&#xff0c;拉取凭证&#xff0c;选择需要的分支 构建 勾选 构建环境 下删除原始 build 配置&#xff0c;防止文件错误 Pre Steps 构建前处理 pom.xml &#xff0c;例如我是需要删除该模块的所有子模块配置&#xff0c;我这里…

【计算机毕设小程序案例】基于SpringBoot的小演员招募小程序

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 &#x1f449;IT源码社-SpringBoot优质案例推荐&#x1f448; &#x1f449;IT源码社-小程序优质案例…

java-- 静态数组

1.静态初始化数组 定义数组的时候直接给数组赋值。 2.静态初始化数组的格式&#xff1a; 注意&#xff1a; 1."数据类型[] 数组名"也可以写成"数据类型 数组名[]"。 2.什么类型的数组只能存放什么类型的数据 3.数组在计算机中的基本原理 当计算机遇到…

Redis 配置文件(redis.conf)中文注释及说明

文章目录 一、概述二、觉见基础配置1.1 导入另一个配置文件1.2 添加Redis扩展1.3 绑定Redis服务在那些网卡上&#xff0c;也就是远程可以通过那个的IP地址访问。1.2 指定Redis服务监听端口1.2 最大分配内容大小1.2 后台服务方式运行1.2 日志记录文件1.2 添加扩展 三、完整配置文…

【EI会议征稿】 2024年遥感、测绘与图像处理国际学术会议(RSMIP2024)

2024年遥感、测绘与图像处理国际学术会议(RSMIP2024) 2024 International Conference on Remote Sensing, Mapping and Image Processing 2024年遥感、测绘与图像处理国际学术会议(RSMIP2024)将于2024年1月19日-21日在中国厦门举行。会议主要围绕遥感、测绘与图像处理等研究领…

为什么进行压力测试? 有哪些方法?

在信息技术飞速发展的今天&#xff0c;软件系统的性能已经成为了用户满意度的决定性因素之一。而要确保一个系统在实际使用中能够稳定可靠地运行&#xff0c;压力测试就显得尤为关键。本文将深入探讨什么是压力测试&#xff0c;为什么它是如此重要&#xff0c;以及一些常见的压…

Python深度学习实战-基于tensorflow.keras六步法搭建神经网络(附源码和实现效果)

实现功能 第一步&#xff1a;import tensorflow as tf&#xff1a;导入模块 第二步&#xff1a;制定输入网络的训练集和测试集 第三步&#xff1a;tf.keras.models.Sequential()&#xff1a;搭建网络结构 第四步&#xff1a;model.compile()&#xff1a;配置训练方法 第五…

k8s-----24、亲和力Affinity

1、应用场景 pod和节点间的关系&#xff1a; 某些Pod优先选择有ssdtrue标签的节点&#xff0c;如果没有在考虑部署到其它节点;某些Pod需要部署在ssdtrue和typephysical的节点上&#xff0c;但是优先部署在ssdtrue的节点上; pod和pod间的关系&#xff1a; 同一个应用的Pod不…