浅谈qt 布局器

在一个颜值当道的今天,无论买衣服,买车还是追星,颜值的高低已经变成了大家最看重的(不管男性女性都一样,千万别和我说你不是);而对于程序猿来说,开发一款软件,不再只注重逻辑和稳定性,美观和用户友好性也是我们不得不关注的一个重点了。

我们进入正题,今天主要和大家分享一下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

时间: 2024-10-23 02:47:13

浅谈qt 布局器的相关文章

( 转)浅谈QT中窗口刷新事件

浅谈QT中窗口刷新事件 [日期:2011-06-25] 来源:Linux社区  作者:袁硕 [字体:大 中 小] 经过一个星期的项目初步开发,写此文就开发时遇到的一些常见问题,给出些资料和自己的观点,希望能给其他的初学者或者参赛的选手一点帮助,当然,也算是一种抛砖引玉,大家有什么好的技巧经验什么的,也能多多分享,借助这次比赛,我们共同进步~ 如果大家都是跟我一样,刚刚开始接触QT,开始开发QT的程序,肯定也会有很多不习惯的地方,今天我重点想谈的就是这么一个不习惯的地方——QT中窗口刷新事件. 对

浅谈Python装饰器

一.概念 装饰器是Python语言中的高级语法.主要的功能是对一个函数.方法.或者类进行加工,作用是为已经存在的对象添加额外的功能,提升代码的可读性.装饰器是设计模式的一种,被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.在实际应用中也经常会用到装饰器.这篇文章来简单谈一下装饰器的实现方式. 二.闭包 因为装饰器是基于闭包来实现的,这里简单说下Python的闭包.看下面的代码: def outer(): var = 3 def inner(): print(var) retu

浅谈QT打印功能实现

QT作为一款轻量级的集成开发环境,其设计的目标是使开发人员利用QT这个应用程序框架更加快速及轻易的开发应用程序.要达到此目的,要求QT必须能够跨平台,QT能够在32位及64位的Linux,MAC OS X以及Windows上运行. 现在我们想在项目中加入一项打印功能,即使在不同的操作系统环境下,仍然能有相同的用户体验,在实现中发现QT对打印的支持不是那么友好.我们希望在跨平台的情况下,能打印各种文档,比如用户的简历,发现如果不调用对应操作系统的内核外壳打印函数,这项工作变得异常艰难.我们希望用Q

我的QT5学习之路(一)——浅谈QT的安装和配置

一.前言 说到Qt,不能不说到C++,这门伟大的语言.因为其面向对象的编程思想和陡峭的学习曲线,一开始学习起来很是吃力.Qt从QT4开始基本封装了很多C++的工具库和界面库,而且支持跨平台,这是它最大的优势.相比于古老的MFC和使用C#的WPF来说,我更喜欢Qt来进行C++的界面设计,这也是我从新开始拾起Qt学习之路的原因. 说完了感受和学习的原因,就开始介绍Qt5了.我这里只做简单的介绍,重要的还是在学习过程中体会Qt的编程逻辑和设计思想. Qt,坦白来说,并不只是一个界面库,他是C++编程思

浅谈Qt事件的路由机制:鼠标事件

请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正. 这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键盘按键事件的时候,也用得毫无问题,因此也没怎么注意过,翻了下一般qt的教材<精通Qt4编程(第二版)>,里面12.1是这么说的. 当用户按下一个鼠标键时,这个事件首先被发给当前拥有焦点的窗口部件. 看到这里,我第一反应是,真的是这样吗,我表示十分地好奇,于是就赶忙试验了一下.代码比较简单,没有注释

【转】浅谈LLDB调试器

随着Xcode 5的发布,LLDB调试器已经取代了GDB,成为了Xcode工程中默认的调试器.它与LLVM编译器一起,带给我们更丰富的流程控制和数据检测的调试功能.LLDB为Xcode提供了底层调试环境,其中包括内嵌在Xcode IDE中的位于调试区域的控制面板,在这里我们可以直接调用LLDB命令.如图1所示: 图1:位于Xcode调试区域的控制台 在本文中,我们主要整理一下LLDB调试器提供给我们的调试命令,更详细的内容可以查看The LLDB Debugger. LLDB命令结构 在使用LL

浅谈flex布局

Flex布局,俗称弹性布局,有了这个布局,咱们做的事情很多,以前那些很难实现比如说垂直居中之类都不存在了. 盒模型布局依赖于float,display,定位之类的方式来布局,这种的布局对一些特殊布局来说很不方便,就如上面的垂直居中就不太好实现. 现在就让我来介绍一个Flex布局方式 他中的一些属性: flex-direction flex-wrap flex-flow justify-content align-items align-content 在这里,声明一点,使用了display:fl

浅谈ul布局以及table布局

我个人对于某些言论说要注重html语义化在布局中的应用,我反而不怎么感冒,试试兼容IE7&&项目期相对较赶的情况下,我还是推荐快速开发为主,兼容性强为主. 如果布局中需要用户边框,推荐div或者table布局:如果不需要边框,ul其实也是不错的一种布局方式. ul布局可以很好地适应布局内容自顶向上对齐地方式,如图.table永远都是垂直居中的方式             代码 ul布局css ul{ list-style-type: none; padding-left: 0px; mar

浅谈Struts2拦截器的原理与实现

拦截器与过滤器           拦截器是对调用的Action起作用,它提供了一种机制可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也是提供了一种可以提取action中可重用的部分的方式,很多业务逻辑都是靠拦截实现的,比如校验,验证登录权限(比如下载时跳转到登陆页面)等等.     过滤器是对整个的请求过程起作用!换句话说就是拦截器没有过滤器的范围广.过滤器是在java web中,你传入的request,response提前过滤掉一些信息