浅谈Qt中的布局管理
2014-10-20龚丽
摘要:Qt布局管理的目标是将放置于窗体中的每一个部件都给定一个合适的位置和大小,常用的有QHBoxLayout水平布局管理器、QVBoxLayout垂直布局管理器、QgridLayout网格布局管理器。Qt程序员在完成窗体界面设计时,可通过可视化的方法搭建界面并布局;也可以纯粹手工编写C++源代码来实现界面设计,编码的方式更适合较复杂的布局。
关键词:Qt布局管理;水平布局;垂直布局;网格布局;可视化方式;编码方式
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)25-5883-04
Qt是一个跨平台的 C++图形用户界面库,1991年由奇趣科技开发。2008年,奇趣科技被诺基亚公司收购,Qt也因此成为诺基亚旗下的编程语言工具,2012年8月Digia宣布对Qt业务及其技术全面收购。Qt技术的传统优势都在桌面和嵌入式系统,目前Digia将移动互联网平台定位为其主要的发展方向,很快将迎来Qt的移动时代。
Qt布局管理是设计应用程序窗体界面时必须考虑的问题,它的目标是将放置于窗体中的每一个部件都给定一个合适的位置和大小,即使窗口尺寸大小被改变了,仍能就保证窗体上的部件始终摆放得美观合适。Qt程序员有两种途径来完成窗体界面的设计和布局:第一种通过可视化的方法搭建界面,由菜单或工具栏中的布局管理器实现布局,可视化的方式比手工编码更简洁快速;第二种方式纯粹手工编写C++源代码来实现界面设计,这种方式更适合较复杂的布局。
Qt提供了多个用于窗口布局的类,编写界面代码时可根据需求定义相应的布局类对象。常用的有:QHBoxLayout、QVBoxLayout、QGridLayout三种,分别是水平布局管理器、垂直布局管理器、网格布局管理器。使用Qt布局管理器可以确保窗体能够自动适应于不同的字体、语言和系统平台。
1 水平布局管理器和垂直布局管理器
QHBoxLayout,水平布局管理器,把窗口部件按照从左到右的顺序排列布局;QVBoxLayout,垂直布局管理器,把窗口部件按照从上到下的顺序排列布局。比如应用程序需要创建一个登录窗口,我们来看看界面设计方法。
1.1 可视化的方式
首先从窗口部件工具箱中拖拽控件图标将其放到窗体中的大概位置,空白处可放入水平分隔符,这时分隔符会显示为一个蓝色的弹簧,但在最终结果的窗体中它是不可见的。然后按照功能需求在属性编辑器中修改每一个窗口部件的属性。此时的界面效果如图1所示。
这时在窗体上出现的红线是已创建的布局,但在窗体运行时,它们是不会出现的。
1.2 编码实现方式
使用纯粹编码的方式来设计登录窗体界面,首先要在登录窗体的头文件中声明各个控件,再在其源文件的构造函数中创建,布局也在构造函数中实现。代码如下:
loginDlg::loginDlg(QWidget *parent) :QDialog(parent)
{
setWindowTitle("Layout");
usernameLabel=new QLabel(tr("用户名:")); //创建各个控件
usernameEdit=new QLineEdit();
passLabel=new QLabel(tr("密码:"));
passEdit=new QLineEdit();
okButton=new QPushButton(tr("登录"));
cancleButton=new QPushButton(tr("取消"));
QVBoxLayout *mainLayout=new QVBoxLayout(this); //整体为垂直布局
QHBoxLayout *firstLayout=new QHBoxLayout(this); //第一行的两个控件水平排列
firstLayout→addWidget(usernameLabel);
firstLayout→addWidget(usernameEdit);
mainLayout→addLayout(firstLayout);
QHBoxLayout *secondLayout=new QHBoxLayout(this); //第二行的两个控件水平排列
secondLayout→addWidget(passLabel);
secondLayout→addWidget(passEdit);
mainLayout→addLayout(secondLayout);
QHBoxLayout *thirdLayout=new QHBoxLayout(this); //第三行的两个控件水平排列
thirdLayout→addWidget(okButton);
thirdLayout→addWidget(cancleButton);
mainLayout→addLayout(thirdLayout);
this→setLayout(mainLayout);
}
窗体运行时效果如图4所示。在这种方式中,我们使用了3个水平布局管理器,1个垂直布局管理器,单纯使用这两种布局管理器的组合实现布局,虽然比较直观,但代码量也比较大。其实,我们还有另外一种更适合实现这种应用程序窗体布局的方法:使用网格布局管理器QGridLayout。
图4
2 网格布局管理器
QGridLayout,网格布局管理器,其含义就是将窗体分隔成行和列的网格来进行排列,将窗口部件整齐摆放,每个网格的单元格里放一个部件。如图5所示。
类似上图这种5行2列的布局比较容易实现,只需要把各个部件填入到指定的单元格里即可。在可视化设计环境下把相应窗口部件拖拽到窗口界面,然后由菜单或工具栏上的
gridLayout→addWidget(Label1, 0, 0); // 将Label1填到(0, 0)单元格
gridLayout→addWidget(LineEdit1, 0, 1); // 将LineEdit1填到(0, 1) 单元格
但是很多程序的窗体界面并不是一个规则的网格结构,这时网格布局管理器就显示了它强大的灵活性,对于不规则排列的控件,可以看作跨行或跨列摆放,代码表述为:
Layout→addWidget(widget, row, column, rowSpan, columnSpan );
其中,widget是要布局的窗口部件,(row, column )是该部件所占用的左上角单元格,rowSpan是该部件要占用的行数,而columnSpan是该部件要占用的列数。rowSpan和columnSpan省略则默认为1。
举例来说,比如图6所示界面,第一行的两个部件是比较规矩的处于两个单元格内,但是第二行的QCheckBox部件就横跨了两列,即在水平方向上占用了两个单元格,那么使用网格排列布局的代码如下:
图6
gridLayout→addWidget(QLabel, 0, 0); // QLabel在(0, 0)
gridLayout→addWidget(QLineEdit, 0, 1); // QLineEdit在(0, 1)
gridLayout→addWIdget(QCheckBox, 1, 0, 1, 2); // QCheckBox起始于(1, 0),纵向占1行,横向跨2列
再比如图7所示界面,QTreeWidget部件纵向跨越了三行(即在垂直方向上占用了这一列三个单元格),对应的布局代码:
图7
gridLayout→addWidget(QTreeWidget, 0, 0, 3, 1); // QTreeWidget起始于(0, 0),并纵向跨3行,横向占1列
gridLayout→addWidget(QPushButton1, 0, 1); // 第一个QPushButton在(0, 1)
gridLayout→addWIdget(QPushButton2, 1, 1); // 第二个QPushButton在(1, 1)
gridLayout→addWIdget(QPushButton3, 2, 1); // 第二个QPushButton在(2, 1)
下面来看一个网格布局编程实例。图8所示界面是一个网络聊天程序的客户端窗口,由列表控件、行文本编辑器、标签控件、按钮等搭建而成,我们使用网格布局管理器来编程,对应的构造函数代码:
图8
TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f): QDialog(parent,f)
{setWindowTitle(tr("聊天室客户端"));
contentListWidget = new QListWidget; //定义各窗口部件
sendLineEdit = new QLineEdit;
sendBtn = new QPushButton(tr("发送"));
userNameLabel = new QLabel(tr("用户名:"));
userNameLineEdit = new QLineEdit;
serverIPLabel = new QLabel(tr("服务器地址:"));
serverIPLineEdit = new QLineEdit;
portLabel = new QLabel(tr("端口:"));
portLineEdit = new QLineEdit;
enterBtn = new QPushButton(tr("进入聊天室"));
QGridLayout *mainLayout = new QGridLayout(this); //定义网格布局管理器
mainLayout→addWidget(contentListWidget,0,0,1,2); //QListWidget横向跨2列
mainLayout→addWidget(sendLineEdit,1,0); //各部件放入对应单元格中
mainLayout→addWidget(sendBtn,1,1);
mainLayout→addWidget(userNameLabel,2,0);
mainLayout→addWidget(userNameLineEdit,2,1);
mainLayout→addWidget(serverIPLabel,3,0);
mainLayout→addWidget(serverIPLineEdit,3,1);
mainLayout→addWidget(portLabel,4,0);
mainLayout→addWidget(portLineEdit,4,1);
mainLayout→addWidget(enterBtn,5,0,1,2); //QPushButton横向跨2列
}
3 结束语
本文所介绍的这三种布局管理器是Qt中最常用的布局管理器,在做界面布局的时候,可以使用网格布局管理器做整体框架设计,然后在其中包含一些水平或垂直布局管理器,或者他们的组合,即通过布局管理器的嵌套使用实现更复杂的界面效果。Qt中可以执行布局管理功能的其他类还有QStackLayout、QSplitter、QScrollArea、QMdiArea等。
参考文献:
[1] 闫锋欣.C++ GUI Qt4编程[M]. 2版.北京: 电子工业出版社,2013.
[2] 郑阿奇.Qt4 开发实践[M].北京:电子工业出版社,2011.