在一个颜值当道的今天,无论买衣服,买车还是追星,颜值的高低已经变成了大家最看重的(不管男性女性都一样,千万别和我说你不是);而对于程序猿来说,开发一款软件,不再只注重逻辑和稳定性,美观和用户友好性也是我们不得不关注的一个重点了。
我们进入正题,今天主要和大家分享一下Qt方面关于布局管理器的使用;
一、基本概念
Qt 提供了几种在窗口部件上管理子窗口部件的基本方式。一共有3 种方法用于管理窗体上子窗口部件的布局:绝对位置法、人工布局法和布局管理器法。相比于使用固定尺寸和位置,布局提供了功能强大且极具灵活性的另一种方案。使用布局后,编程人员无需计算尺寸和位置,布局可以自动进行调整,符合用户屏幕、语言以及字体的要求。
1.绝对位置法
这种方法是最原始的拖放窗口部件的方法。它对窗体的各个子窗口部件分配固定的大小和位置,是通过调用基类QWidget 提供的setGeometry()函数来实现的。
所以绝对位置法有很多缺点:
1> 用户无法改变窗口的大小,当父窗口改变时,子窗口不能做出相应的调整。
2>如果用户选择的字体太大或者翻译成多国语言,特别是俄语,很多都会显示不全被截断。
3> 对于不同风格的平台,这些窗口部件可能会具有并不合适的尺寸大小。
4>必须人工计算这些位置和大小。这样做不仅非常枯燥而且极易出错,并且还会让后
期的维护工作变得痛苦万分。
很显然,使用这种方式管理GUI 应用程序大大降低了程序员的开发效率,降低了应用
程序的质量和适应性。
2.人工布局法
这种方法的核心是通过重载QWidget::resizeEvent(QResizeEvent*)函数来使得子窗口
的的大小尺寸总是和父窗口的大小成比例,也就在一定程度上减轻了计算量,但是在其中也
要通过setGeometry()函数来设置子窗口部件的位置和大小。在程序的规模比较小,并且不需要时常变更设计的情况下,绝对位置法勉强可以胜任。但是它就像前面的绝对位置法一样,仍然需要计算许多手写代码中的常量,尤其是当设计被改变的时候,这种情况更加突出,而且它并没有消除文本会被截断的危险。辅以社会自子窗口部件的大小提示,应该可以规避这种风险,但是这样会使代码变得尤为复杂。
3.布局管理器法
这种方式是使用Qt 设计用户界面、组织管理Qt 窗口部件的最好方法。布局管理器为
窗口部件提供了能变化的默认值(sensible default sizes),可以随着窗口部件大小的变化,对子窗口部件的大小和位置做出适当的调整。
二、详细使用说明
QLayout 类是Qt 的几何管理器的基类,它派生自QObject 类和QLayoutItem 类,是一
个抽象基类,必须被派生类所重新实现。它的派生类主要有QBoxLayout, QGridLayout, QFormLayout 以及QStackedLayout。而QBoxLayout
又有两个主要的Qt4 子类,QHBoxLayout 和QVBoxLayout
1、水平布局管理器:QHBoxLayout,按水平方向组织管理控件;
2、垂直布局管理器:QVBoxLayout,按垂直方向组织管理控件;
3、网格布局管理器:QGridLayout,按照二维网格组织管理控件;
4、表单布局管理器:QFormLayout,表单布局管理器主要用作管理界面上的输入窗口部件( input widgets)以及和它们相连的标签窗口部件(labels)。
5、栈布局管理器:QStackeLayout,类似于栈的方式管理控件,不过Qt设计器不知什么原因没有提供它的布局管理器(我认为开发人员觉得前几种已经能满足几乎所有的布局需要,栈布局使用太过复杂,不如用一个控件代替),提供了一个栈控件(QStackedWidget);在实际应用中使用前三种混合基本都能满足设计需求。
我们来看,第一种水平布局:
效果如图:1.1
[attachment=15390]
1.1
第二种垂直布局:
效果如下图1.2
[attachment=15391]
1.2
第三种 网格布局:
效果如下图 1.3
[attachment=15392]
1.3
第四种 表单布局
效果如下图 1.4
[attachment=15393]
1.4
第五种是栈布局,我的4.7.0 版本,Qt Designer 的窗口部件盒没有可视化的提供对栈布局管理器的支持,只提供了一个栈部件QStackedWidget,作用与栈布局管理器类似。因此,在使用Qt Designer 绘制GUI界面时,完全可以使用QStackedWidget 来代替QStackedLayout。在此不做赘述。
2.1下面来讲讲案例:
当然是用设计器拖出来最简单方便,我们后面再用代码写;
1.用设计器 添加五个控件;
2.选中是个button点击右键选择布局,我们选择栅格布局(你可以看情况自己选择合适的);
[attachment=15395]
2.1
3.将刚才布局的控件和文本框一起选中,点击右键再选择你需要的布局方式(我们选择水平);
[attachment=15395]
2.2
4.效果图如下:
2.3
这里我们就要注意调整空白和控件之间间距的问题;
2.4
1.空白(margin)和间距(spacing)
每种布局都有两个重要的属性,空白和间距。空白指的是整个布局四周距离窗体边缘
的距离;间距指的是布局管理器内部各个窗口部件之间的距离。空白属性即margin(),间距属性即spacing(),它们的默认值是有窗体的风格决定的。Qt 的默认风格下,子窗体部件的margin()的值是9 英寸。spacing()的值与margin()相同。如果要设置这两个值可以通过setMargin()和setSpacing()。注意,从Qt4.3 开始,margin()属性已经逐渐不再被Qt4 所推荐,更好的设置空白的方法是使用setContentsMargins()方法,
它的原型如下:
void QLayout::setContentsMargins ( int left, int top, int right, int bottom )
其中,left, top, right, 和bottom 表示环绕在布局周围的空白。对于QGridLayout 和QFormLayout,不要使用setSpacing()方法,而是要分别使用setHorizontalSpacing()和setVerticalSpacing()方法来设置水平和垂直方向
2.大小约束(size constraint)
影响布局方式的另一种方法是设置它的子窗口部件的最大大小、最小大小或固定大小。这些是通过设置sizeConstraint 属性来完成的。该属性值是一个枚举常量,定义了布局的大小约束的模式。表列出了它所有可能的取值,它的默认值是QLayout::SetDefaultConstraint。获取和设置该属性值可以通过QWidget::layout()来获取主窗口部件的布局管理器,然后可以调用QLayout::sizeConstraint()函数来查看当前的设置情况,然后再通过QLayout::setSizeConstraint()函数来设置该布局管理器的sizeConstraint 属性。这两种函数的原型如下:SizeConstraint sizeConstraint () const
void setSizeConstraint ( SizeConstraint )其中,SizeConstraint 的取值可以在QLayout类的枚举中得到;
QLayout::SetDefaultConstraint 0 主窗口部件的最小尺寸设置为minimumSize(),除非该窗口部件已经有一个最小尺寸
QLayout::SetFixedSize 3 主窗口部件的尺寸设置为sizeHint(),并且不允许改变该窗口部件的尺寸
QLayout::SetMinimumSize 2 主窗口部件的最小尺寸设置为minimumSize(),并且该窗口部件不能够变得更小
QLayout::SetMaximumSize 4 主窗口部件的最大尺寸设置为maximumSize(),并且该窗口部件不能够变得更大
QLayout::SetMinAndMaxSize 5 主窗口部件的最小尺寸设置为minimumSize(),最大尺寸设置为
3.大小策略(size policy)
一个窗口部件的大小策略会告诉布局系统应该如何对它进行拉伸或收缩。Qt 为它所有
的内置窗口部件都提供了合理的默认大小策略值,但是由于不可能为每一种可能产生的布局
都提供唯一的默认值,所以在一个窗体中,开发人员改变它上面的一个或两个窗口部件的大
小策略是非常普遍的现象。一个QSizePolicy 既包含一个水平分量也包含一个垂直分量。
可以通过QSizePolicy 找到对应的枚举值;
4.伸缩因子(stretch factor)
除了大小策略中包含的水平方向和垂直方向两个分量之外, QSizePolicy 类还保存了水平方向和垂直方向的一个伸缩因子。这些伸缩因子可以用来说明在增大窗体时,对不同的子窗口部件应使用的不同放大比例。即需要设置QSizePolicy::horizontalStretch 和
QSizePolicy::verticalStretch 的值来实现。默认情况下,被布局管理器组合在一起的窗
口部件的伸缩因子是相等的,都为0。
2.2 移除布局
选择想要移除的布局,点击右键或者如下图在设计器工具栏上有个“打破布局”
如图:
[attachment=15398]
2.5
2.3 一些快捷键
常见的布局操作所对应的快捷键。
水平布局Ctrl+1 将选中的界面元素置于一个水平布局中;
垂直布局Ctrl+2 将选中的界面元素置于一个垂直布局中;
栅格布局Ctrl+5 将选中的界面元素置于一个栅格布局中;
表单布局Ctrl+6 将选中的界面元素置于一个表单布局中;
分裂器水平布局Ctrl+3 创建一个分裂器水平布局,并将选中的界面元素置于其中;
分裂器垂直布局Ctrl+4 创建一个分裂器垂直布局,并将选中的界面元素置于其中;
调整大小Ctrl+J 调整布局的大小,以使得位于其中的元素能够恰当的显示自身内容。关于这方面的内容,可以参见QWidget::adjustSize()函数;
破除布局Ctrl+0 破除选中的布局;
2.4 手写代码
QWidget *pWidget = new QWidget;
pWidget->setWindowTitle("Calculator");
pWidget->show();
QLineEdit *pText = new QLineEdit(pWidget);
pText->setMinimumSize(150,100);
QPushButton *pBtnAdd = new QPushButton("+",pWidget);
QPushButton *pBtnSub = new QPushButton("-",pWidget);
QPushButton *pBtnMul= new QPushButton("*",pWidget);
QPushButton *pBtnDiv= new QPushButton("/",pWidget);
QVBoxLayout *pVBox = new QVBoxLayout(pWidget);
QGridLayout *pGBox = new QGridLayout();
pVBox->addWidget(pBtnAdd);
pVBox->addWidget(pBtnSub);
pVBox->addWidget(pBtnMul);
pVBox->addWidget(pBtnDiv);
pVBox->setSpacing(10);
pWidget->setLayout(pVBox);
pGBox->addWidget(pBtnAdd,0,0);
pGBox->addWidget(pBtnSub,0,1);
pGBox->addWidget(pBtnMul,1,0);
pGBox->addWidget(pBtnDiv,1,1);
pVBox->addWidget(pText);
pVBox->addLayout(pGBox);
pVBox->setMargin(12);
pWidget->setLayout(pVBox);
效果如下图2.6:
2.6
2.5 总结
当界面元素较为复杂时,应该毫不犹豫的尽量使用网格布局,而不是使用水平和垂直布局的组合或者嵌套的形式,因为在多数情况下,后者往往会使“局势”更加复杂而难以控制。网格布局赋予了界面设计器更大的*度来排列组合界面元素,而仅仅带来了微小的复杂度开销。当要设计的界面是一种类似于两列和若干行组成的形式时,使用表单布局要比网格布局更为方便些。
上面分享了自己关于布局的基础使用方式的理解,若有不对之处敬请指正。
http://www.qtcn.org/bbs/apps.php?q=diary&a=detail&did=2198&uid=130507
浅谈qt 布局器的更多相关文章
-
浅谈 Qt 布局那些事
Qt 布局那些事是本文介绍的内容,直接进入主题.GridLayout是一个非常强大的布局管理器,它可以实现很多复杂的布局,名字中暗示它将所有控件放置在类似网格的布局中.^__^GridLayout有两 ...
-
浅谈Python装饰器
一.概念 装饰器是Python语言中的高级语法.主要的功能是对一个函数.方法.或者类进行加工,作用是为已经存在的对象添加额外的功能,提升代码的可读性.装饰器是设计模式的一种,被用于有切面需求的场景,较 ...
-
浅谈Qt事件的路由机制:鼠标事件
请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正. 这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键 ...
-
浅谈QT打印功能实现
QT作为一款轻量级的集成开发环境,其设计的目标是使开发人员利用QT这个应用程序框架更加快速及轻易的开发应用程序.要达到此目的,要求QT必须能够跨平台,QT能够在32位及64位的Linux,MAC OS ...
-
我的QT5学习之路(一)——浅谈QT的安装和配置
一.前言 说到Qt,不能不说到C++,这门伟大的语言.因为其面向对象的编程思想和陡峭的学习曲线,一开始学习起来很是吃力.Qt从QT4开始基本封装了很多C++的工具库和界面库,而且支持跨平台,这是它最大 ...
-
浅谈设计模式--建造器模式(Builder Pattern)
建造器模式,是于创建带有大量参数的对象,并避免因参数数量多而产生的一些问题(如状态不一致-JavaBean的setter模式). 如果参数多且有些是必须初始化的,有些是不一定需要初始化的时候,创建对象 ...
-
浅谈Struts2拦截器的原理与实现
拦截器与过滤器 拦截器是对调用的Action起作用,它提供了一种机制可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也是提供了 ...
-
浅谈 WPF布局
我们首先来了解一下图形化用户界面(Graphic User Interface)也就是我们常常听到的GUI.举个简单的例子,同样是数据,我们可以用控制台程序加格式控制符等输出,但是这些都不如GUI来的 ...
-
浅谈CSS布局
在No.4中谈及了下盒子模型,引出布局模型 1.布局模型有三类: 1)流动模型 flow(默认) 2)浮动模型 float 3)层模型 layer 2.文档流 :指的是文本沿着从左到右的方向展开 ...
随机推荐
-
ADO.net操作数据库
今天整理硬盘,发现2年前开始着手开始学习C#的学习日记.陆续整理,一是自己的知识梳理梳理,二是希望与大家多多交流,能给初学者带来一定帮助,当然是更高兴的啦. 断线对象 另一类是与数据源无关的断线对象, ...
-
android 入门-控件 测量状态栏高度
private ViewTreeObserver viewTreeObserver; /** 获取可見区域高度 **/ WindowManager manager = getWindowManager ...
-
.NET Framework 4.0-RequestValidationMode
1.WebForm 先看如下 web.config 的代码: <system.web> <compilation debug="true" targetFrame ...
-
Bootstrap入门(四)表格
Bootstrap入门(四)表格 <table>标签 首先,引入bootstrap的css文件,然后表格内容放在一个class为table的<table>标签中(class=& ...
-
C# 获取一个独一无二的字符串 GUID
在保存文件,创建目录时,为了保证名称不重复,经常使用Random产生一个随机数,有更简单且不会重复的办法是: Guid.NewGuid().ToString() 就会生成一个类似 37c1acec-4 ...
-
linux发布环境初始化脚本
#参数配置 homeDir=$(pwd) tomcatDir=$homeDir/tomcat logDir=$homeDir/tomcat/logs backUpDir=$homeDir/backup ...
-
使用FreeSWITCH做电话自动回访设置
一.背景介绍: 目前公司在处理客户回访方面,需要人工进行电话回访,尤其是逢年过节的时候,电话问候更能体现服务的品质: 在某些公司,电话销售员需要给大批量的陌生用户打电话,如果能过滤掉不关心的用户,销售 ...
-
spring3-mvc-maven-hello-world-master mvn jetty:run 及 mvn war:war 指令
spring3-mvc-maven-annotation-hello-world-master mvn jetty:run Run this project locally Terminal $ m ...
-
K-means算法的实现
K-MEANS算法是一种经典的聚类算法,在模式识别得到了广泛的应用.算法中有两个关键问题需要考虑:一是如何评价对象的相似性,通常用距离来度量,距离越近越相似:另外一个是如何评价聚类的效果,通常采用误差 ...
-
HDU 2093 考试排名 模拟题
解题报告: 题目描述:写一个程序给一个编程考试C++实时提交系统排名,给你的数据是题目的总数,每次错误提交罚的时间分,每位用户的姓名,然后是输入用户每题的完成情况,有一下几种情况,第一,输入只有一个正 ...