GUI的布局管理是GUI开发中非常重要的一个环节,一个设计良好的GUI界面,其对应的布局排布也是非常必须的。其中布局管理就是要管理窗口中部件的放置。常用两种方式来实现布局:绝对位置 布局(Absolute Layout)实现,布局类(QLayout)实现。
绝对位置 布局(Absolute Layout)主要是在程序中通过指定每一个组件显示的坐标和大小。由于影响绝对布局显示的因素很多(平台的差异,窗口大小的差异,显示字体大小等因素),所以在本文中主要以QLayout的基本布局进行说明。
常用到的布局类有QHBoxLayout,QVBoxLayout,QGridLayout ,QFormLayout4种,分别水平排列布局,垂直排列布局,表格排列布局,以及。布局中最常用的方法有addWidget()和addLayout(),addWidget()方法用于在布局中插入控件,addLayout()用于在布局中插入子布局。
水平布局管理器(QHBoxLayout)可以把添加的控件以水平的顺序依次排开;
垂直布局管理器(QVBoxLayout)可以把添加的控件以垂直的顺序依次排开;
网格布局管理器(QGridLayout)可以以网格的形式,把添加的控件以一定矩阵排列;
窗体布局管理器(QFormLayout)可以以两列的形式排列所添加的控件
- 水平(垂直)布局管理:
QHBoxLayout,按照从左到右的顺序进行添加控件。
QVBoxLayout,按照从上到下的顺序进行添加控件。
QHBoxLayout和QVBoxLayout用法基本相同。这里以水平布局管理器QHBoxLayout为例来说明。
class QHBoxLayout(QBoxLayout)
| QHBoxLayout()
| QHBoxLayout(QWidget)
常用方法:
| addLayout(…)
| QBoxLayout.addLayout(QLayout, int stretch=0)
在box的底部添加布局,其中默认的拉伸因子为0
| addWidget(…)
| QBoxLayout.addWidget(QWidget, int stretch=0, Qt.Alignment alignment=0)
为布局中添加控件,stretch(拉伸因子)只适用与QBoxLayout,widget和box会随着stretch的变大而增大;alignment指定对齐的方式
| addSpacing(…)
| QBoxLayout.addSpacing(int)
通过该方法增加额外的space。
- 网格布局管理器:
将窗体分隔成行和列的网格来进行排列(可以认为是二维的数据排布)。通常可以使用函数addWidget()或者addLayout()来将被管理的widget或者layout添加到窗格中。也可以通过重载的函数addWidget()或者addLayout()的行和列跨度实现占据多个窗格。
class QGridLayout(QLayout)
| QGridLayout(QWidget)
| QGridLayout()
常用方法:
添加组件
| addWidget(…)
| QGridLayout.addWidget(QWidget)
| QGridLayout.addWidget(QWidget * widget, int row, int column, Qt.Alignment alignment = 0 )
QWidget:为所添加的组件
row:为组件要添加的行数,默认从0开始
column:为组件要添加到的列数,默认从0开始
alignment:对齐的方式
| QGridLayout.addWidget(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt.Alignment alignment = 0)
当添加的组件跨越很多行或者列的时候,使用该方法。
QWidget:为所添加的组件
fromRow:为组件起始的行数
fromColumn:为组件起始的列数
rowSpan:为组件跨越的行数
columnSpan:为组件跨越的列数
alignment:对齐的方式
| addLayout(…)
| QGridLayout.addLayout(QLayout, int, int, Qt.Alignment alignment=0)
| QGridLayout.addLayout(QLayout, int, int, int, int, Qt.Alignment alignment=0)
其中参数说明同addWidget.
- 窗体布局管理器:
在窗口中按照两列的形式排列控件,两列控件的类型可以根据使用的场景不同而不同。
class QFormLayout(QLayout)
| QFormLayout(QWidget parent=None)
常用方法:
| addRow(…)
| QFormLayout.addRow(QWidget, QWidget)
| QFormLayout.addRow(QWidget, QLayout)
| QFormLayout.addRow(str, QWidget)
| QFormLayout.addRow(str, QLayout)
| QFormLayout.addRow(QWidget)
| QFormLayout.addRow(QLayout)
如何实现如上的布局界面,先分析一下该界面的整体布局是如何排布的。
QVBoxLayout(mainLayout)中包含QHBoxLayout和QFormLayout.其中QHBoxLayout中嵌套了QGridLayout和QVBoxLayout.
看一下具体的代码实现:
#-*- coding:utf-8 -*-
'''
Basic Layout
'''
__author__ = 'Tony Zhu'
import sys
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QApplication, QGroupBox, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QGridLayout, QFormLayout, QLineEdit, QTextEdit
class TianGong(QWidget):
def __init__(self):
super(TianGong,self).__init__()
self.initUi()
def initUi(self):
self.createGridGroupBox()
self.creatVboxGroupBox()
self.creatFormGroupBox()
mainLayout = QVBoxLayout()
hboxLayout = QHBoxLayout()
hboxLayout.addStretch()
hboxLayout.addWidget(self.gridGroupBox)
hboxLayout.addWidget(self.vboxGroupBox)
mainLayout.addLayout(hboxLayout)
mainLayout.addWidget(self.formGroupBox)
self.setLayout(mainLayout)
def createGridGroupBox(self):
self.gridGroupBox = QGroupBox("Grid layout")
layout = QGridLayout()
nameLabel = QLabel("中文名称")
nameLineEdit = QLineEdit("天宫二号")
emitLabel = QLabel("发射地点")
emitLineEdit = QLineEdit("酒泉中心")
timeLabel = QLabel("发射时间")
timeLineEdit = QLineEdit("9月15日")
imgeLabel = QLabel()
pixMap = QPixmap("tiangong.png")
imgeLabel.setPixmap(pixMap)
layout.setSpacing(10)
layout.addWidget(nameLabel,1,0)
layout.addWidget(nameLineEdit,1,1)
layout.addWidget(emitLabel,2,0)
layout.addWidget(emitLineEdit,2,1)
layout.addWidget(timeLabel,3,0)
layout.addWidget(timeLineEdit,3,1)
layout.addWidget(imgeLabel,0,2,4,1)
layout.setColumnStretch(1, 10)
self.gridGroupBox.setLayout(layout)
self.setWindowTitle('Basic Layout')
def creatVboxGroupBox(self):
self.vboxGroupBox = QGroupBox("Vbox layout")
layout = QVBoxLayout()
nameLabel = QLabel("科研任务:")
bigEditor = QTextEdit()
bigEditor.setPlainText("搭载了空间冷原子钟等14项应用载荷,以及失重心血管研究等航天医学实验设备 "
"开展空间科学及技术试验.")
layout.addWidget(nameLabel)
layout.addWidget(bigEditor)
self.vboxGroupBox.setLayout(layout)
def creatFormGroupBox(self):
self.formGroupBox = QGroupBox("Form layout")
layout = QFormLayout()
performanceLabel = QLabel("性能特点:")
performanceEditor = QLineEdit("舱内设计更宜居方便天宫生活")
planLabel = QLabel("发射规划:")
planEditor = QTextEdit()
planEditor.setPlainText("2020年之前,中国计划初步完成空间站建设")
layout.addRow(performanceLabel,performanceEditor)
layout.addRow(planLabel,planEditor)
self.formGroupBox.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = TianGong()
ex.show()
sys.exit(app.exec_())
代码分析:
L28~51:
def createGridGroupBox(self):
self.gridGroupBox = QGroupBox("Grid layout")
layout = QGridLayout()
nameLabel = QLabel("中文名称")
nameLineEdit = QLineEdit("天宫二号")
emitLabel = QLabel("发射地点")
emitLineEdit = QLineEdit("酒泉中心")
timeLabel = QLabel("发射时间")
timeLineEdit = QLineEdit("9月15日")
imgeLabel = QLabel()
pixMap = QPixmap("tiangong.png")
imgeLabel.setPixmap(pixMap)
layout.setSpacing(10)
layout.addWidget(nameLabel,1,0)
layout.addWidget(nameLineEdit,1,1)
layout.addWidget(emitLabel,2,0)
layout.addWidget(emitLineEdit,2,1)
layout.addWidget(timeLabel,3,0)
layout.addWidget(timeLineEdit,3,1)
layout.addWidget(imgeLabel,0,2,4,1)
layout.setColumnStretch(1, 10)
self.gridGroupBox.setLayout(layout)
self.setWindowTitle('Basic Layout')
定义QGridLayout布局。其中增加QGroupBox(有标题的组合框在它里面地其它不同窗口部件) ,将QGridLayout添加到QGroupBox中。
在本例中使用了不同参数重载的addWidget()方法。
在QLabel中显示图片。
pixMap = QPixmap(“tiangong.png”)
imgeLabel.setPixmap(pixMap)
layout.setColumnStretch(1, 10) 指定的行,设定其拉伸因子为10。
addWidget (self, QWidget, int, int, Qt.Alignment alignment = 0)
addWidget (self, QWidget, int, int, int, int, Qt.Alignment alignment = 0)
QWidget参数为需插入的控件对象,后面的两个int参数为插入的行和列,再后面两上int参数为跨度的行数和跨度的列数,alignment参数描述各控件的对齐方式。
L53~62:
def creatVboxGroupBox(self):
self.vboxGroupBox = QGroupBox("Vbox layout")
layout = QVBoxLayout()
nameLabel = QLabel("科研任务:")
bigEditor = QTextEdit()
bigEditor.setPlainText("搭载了空间冷原子钟等14项应用载荷,以及失重心血管研究等航天医学实验设备 "
"开展空间科学及技术试验.")
layout.addWidget(nameLabel)
layout.addWidget(bigEditor)
self.vboxGroupBox.setLayout(layout)
定义QVBoxLayout布局。将QVBoxLayout添加到QGroupBox中。通过addWidget()方法增加所需的控件。
L64~75:
def creatFormGroupBox(self):
self.formGroupBox = QGroupBox("Form layout")
layout = QFormLayout()
performanceLabel = QLabel("性能特点:")
performanceEditor = QLineEdit("舱内设计更宜居方便天宫生活")
planLabel = QLabel("发射规划:")
planEditor = QTextEdit()
planEditor.setPlainText("2020年之前,中国计划初步完成空间站建设")
layout.addRow(performanceLabel,performanceEditor)
layout.addRow(planLabel,planEditor)
self.formGroupBox.setLayout(layout
定义QFormLayout布局。将QFormLayout添加到QGroupBox中。通过addRow()方法增加所需的控件。
L19~25:
mainLayout = QVBoxLayout()
hboxLayout = QHBoxLayout()
hboxLayout.addStretch()
hboxLayout.addWidget(self.gridGroupBox)
hboxLayout.addWidget(self.vboxGroupBox)
mainLayout.addLayout(hboxLayout)
mainLayout.addWidget(self.formGroupBox)
定义QVBoxLayout类型的mainLayout,并将定义好的各个layout和groupbox按照嵌套的关系添加到mainLayout中。
关于各个layout中方法的详细使用可以参考pyqt的官网中的定义。