布局管理(绝对&相对水平垂直格栅表单)

Posted chuanxiaopang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了布局管理(绝对&相对水平垂直格栅表单)相关的知识,希望对你有一定的参考价值。

目录

一、绝对布局

二、盒布局

三、格栅布局

四、格栅布局跨行跨列显示

布局管理即设置窗体上各个控件的位置,对于新手来说,这是学习的难点。

布局管理根据绝对坐标是否变动分为绝对布局和相对布局两大类。采用相对布局的窗口在变大或缩小时,各控件的位置关系会保持固定比例做相应变动。而采用绝对布局的窗口变动时,空间位置不会变动。

而相对布局根据方式不同,又可以分为水平布局(QHBoxLayout)、垂直布局管理(QVBoxLayout)、栅格布局管理(QGridLayout)、表单布局管理(QFormLayout)。

一、绝对布局

绝对布局中以像素为单位区分元素的位置,衡量元素的大小,以设定坐标的方式精准的定位每个控件的位置,但是这种布局方式也有缺点:

  • 窗体控件无法根据窗口的位置和大小而变化;
  • 改变字体大小时可能会破坏布局;
  • 当分辨率有较大改变时,原有布局会破坏;
  • 在设计阶段,如果需要添加或删除控件,如果要调整控件位置,就需要全部调整。

下面是绝对布局的示例:

技术图片
 1 import sys,os
 2 from PyQt5.QtWidgets import QWidget,QLabel,QApplication
 3 from PyQt5.QtGui import QIcon
 4 
 5 path = os.path.dirname(os.path.dirname( os.path.dirname(__file__)))
 6 
 7 class MyWindow(QWidget):
 8 
 9     def __init__(self):
10         super(MyWindow, self).__init__()
11         self.initUI()
12 
13     def initUI(self):
14         self.setGeometry(300,300,500,400)
15         self.setWindowIcon(QIcon(r%s4.图标素材chuan.ico % path))
16         self.setWindowTitle(绝对布局示例)
17 
18         lbl1 = QLabel(这是第一个标签,self)
19         lbl1.setGeometry(80,80,30,30)
20 
21         lbl2 = QLabel(这是第二个标签,self)
22         lbl2.move(150,150)
23 
24 
25 if __name__ == __main__:
26     app = QApplication(sys.argv)
27     win = MyWindow()
28     win.show()
29     sys.exit(app.exec_())
绝对布局示例

效果图如下:

技术图片

根据效果图可以发现:

  1. 在改变窗口长和宽的时候,两个标签的位置不会变动;
  2. 两个标签用不同的方法创建。第一个标签不仅设定了位置,还固定了大小,所以内容不能完全展示。

二、盒布局(Box Layout)

采用盒布局的窗口在改变窗体大小时,各控件会按相应比例自动调整。代码如下:

技术图片
 1 import sys,os
 2 from PyQt5.QtWidgets import QApplication,QHBoxLayout,QVBoxLayout,QWidget,QPushButton
 3 from PyQt5.QtGui import QIcon
 4 
 5 path = os.path.dirname(os.path.dirname( os.path.dirname(__file__)))
 6 
 7 class MyWindow(QWidget):
 8 
 9     def __init__(self):
10         super(MyWindow, self).__init__()
11         self.initUI()
12 
13     def initUI(self):
14         self.setGeometry(300,300,500,400)
15         self.setWindowIcon(QIcon(r%s/4.图标素材/chuan.ico % path))
16         self.setWindowTitle(盒布局示例)
17 
18         okbutton = QPushButton(确认)  #设置“确认”按钮
19         cancelbutton = QPushButton(取消)  #设置“取消”按钮
20 
21         hbox = QHBoxLayout()  #布局实例化对象
22         hbox.addStretch(1)  #设置分配比例
23         hbox.addWidget(okbutton)  #添加“确认”按钮到窗体
24         hbox.addWidget(cancelbutton)
25 
26         vbox = QVBoxLayout()
27         vbox.addStretch(1)
28         vbox.addLayout(hbox)
29 
30         self.setLayout(vbox) #设置窗体布局
31 
32 if __name__ == __main__:
33     app = QApplication(sys.argv)
34     win = MyWindow()
35     win.show()
36     sys.exit(app.exec_())
盒布局示例

盒布局中使用stretch函数在布局中增加了一个伸缩量,里面的参数表示QSpacerItem的个数,默认值为零(也可以理解为除去控件外,空白部分所占的比例),会将你放在layout中的空间压缩成默认的大小。而且在窗体缩小时,这个伸缩量也可以变小,直至为零。

技术图片

 “确认”和“取消”两个按钮出现在窗体右下角。示例中实现的方法是首先创建一个垂直布局,按钮上部伸缩量占比为1,接着把这整个布局放在水平布局里,伸缩量占比为1.于是实现了给出的显示效果。

下面对addstretch方法做个补充讲解:

技术图片
 1 import sys,os
 2 from PyQt5.QtWidgets import QApplication,QHBoxLayout,QVBoxLayout,QWidget,QPushButton
 3 from PyQt5.QtGui import QIcon
 4 
 5 path = os.path.dirname(os.path.dirname( os.path.dirname(__file__)))
 6 
 7 class MyWindow(QWidget):
 8 
 9     def __init__(self):
10         super(MyWindow, self).__init__()
11         self.initUI()
12 
13     def initUI(self):
14         self.setGeometry(300,300,500,300)
15         self.setWindowIcon(QIcon(r%s/4.图标素材/chuan.ico % path))
16         self.setWindowTitle(addstrtch示例)
17 
18         fir_button = QPushButton(按钮一)  #设置按钮一
19         sec_button = QPushButton(按钮二)  #设置按钮二
20         thir_button = QPushButton(按钮三)  #设置按钮三
21 
22         hbox = QHBoxLayout()
23         hbox.addStretch(1)
24         hbox.addWidget(fir_button)
25         hbox.addStretch(2)
26         hbox.addWidget(sec_button)
27         hbox.addStretch(3)
28         hbox.addWidget(thir_button)
29 
30         # vbox = QVBoxLayout()
31         # vbox.addStretch(1)
32         # vbox.addLayout(hbox)
33 
34         self.setLayout(hbox) #设置窗体布局
35 
36 if __name__ == __main__:
37     app = QApplication(sys.argv)
38     win = MyWindow()
39     win.show()
40     sys.exit(app.exec_())
addstretch方法示例

使用addstretch方法分别给定了参数1、2、3,即在水平布局上,除去按钮部分外的空白区域,按照1:2:3的比例分配空间。下过如下图所示。

技术图片

三、格栅布局

格栅布局是最常用的布局方式,下面我们通过模拟计算器界面的方式来学习格栅布局。

技术图片
 1 import sys,os
 2 from PyQt5.QtWidgets import QApplication,QPushButton,QWidget,QGridLayout
 3 from PyQt5.QtGui import QIcon
 4 
 5 path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
 6 
 7 class MyWindow(QWidget):
 8 
 9     def __init__(self):
10         super(MyWindow, self).__init__()
11         self.initUI()
12 
13     def initUI(self):
14         self.setWindowTitle(格栅布局示例)
15         self.setWindowIcon(QIcon(r%s4.图标素材chuan.ico % path))
16         self.setGeometry(600,300,500,400)
17 
18         names = [On,Off,AC,/,
19                  7,8,9,*,
20                  4,5,6,-,
21                  1,2,3,+,
22                  0,00,.,=]
23 
24         positions = [(i,j) for i in range(5) for j in range(4)]
25 
26         grid = QGridLayout()
27         self.setLayout(grid)
28         for position,name in zip(positions,names):
29             button = QPushButton(name)
30             grid.addWidget(button,*position)
31 
32 
33 
34 if __name__ == __main__:
35     app = QApplication(sys.argv)
36     win = MyWindow()
37     win.show()
38     sys.exit(app.exec_())
格栅布局示例

显示效果如下:

技术图片

下面来分析代码

names = [‘On‘,‘Off‘,‘AC‘,‘/‘,
                 ‘7‘,‘8‘,‘9‘,‘*‘,
                 ‘4‘,‘5‘,‘6‘,‘-‘,
                 ‘1‘,‘2‘,‘3‘,‘+‘,
                 ‘0‘,‘00‘,‘.‘,‘=‘]

names列表是各按键的名称。

positions = [(i,j) for i in range(5) for j in range(4)]

 这个列表生成式生成的列表类似一个矩阵,各元素的数值恰好是按钮在格栅布局中位置

        for position,name in zip(positions,names):
            button = QPushButton(name)
            grid.addWidget(button,*position)

 这里使用的zip函数。python3中为了减少内存,zip函数返回的是一个对象。如果要展示列表,可通过 list() 转换。

names = [‘On‘,‘Off‘,‘AC‘,‘/‘,
                 ‘7‘,‘8‘,‘9‘,‘*‘,
                 ‘4‘,‘5‘,‘6‘,‘-‘,
                 ‘1‘,‘2‘,‘3‘,‘+‘,
                 ‘0‘,‘00‘,‘.‘,‘=‘]
positions = [(i,j) for i in range(5) for j in range(4)]
a = zip(names,positions)

print(a)
print(list(a))

显示效果如下:
<zip object at 0x0000020EFF489508>
[(‘On‘, (0, 0)), (‘Off‘, (0, 1)), (‘AC‘, (0, 2)), (‘/‘, (0, 3)), (‘7‘, (1, 0)), (‘8‘, (1, 1)), (‘9‘, (1, 2)), (‘*‘, (1, 3)), (‘4‘, (2, 0)), (‘5‘, (2, 1)), (‘6‘, (2, 2)), (‘-‘, (2, 3)), (‘1‘, (3, 0)), (‘2‘, (3, 1)), (‘3‘, (3, 2)), (‘+‘, (3, 3)), (‘0‘, (4, 0)), (‘00‘, (4, 1)), (‘.‘, (4, 2)), (‘=‘, (4, 3))]

 四、格栅布局跨行跨列显示

虽然格栅布局最常用,但是实际窗口的控件往往是大小不一的,单个控件跨行跨列很常见,下面来介绍下跨行跨列的情况。

技术图片
 1 import sys,os
 2 from PyQt5.QtWidgets import QWidget,QPushButton,QLabel,QLineEdit,QApplication,QGridLayout
 3 from PyQt5.QtGui import QIcon, QPixmap
 4 
 5 path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
 6 
 7 class MyWindow(QWidget):
 8 
 9     def __init__(self):
10         super().__init__()
11         self.initUI()
12 
13     def initUI(self):
14         self.setWindowTitle(跨行跨列布局示例)
15         self.setWindowIcon(QIcon(r%s4.图标素材chuan.ico % path))
16         self.setGeometry(600,300,450,300)
17 
18         lbl_image = QLabel() 
19         png = QPixmap(r%s4.图标素材cartoon1.ico % path)
20         lbl_image.setPixmap(png)
21         lbl_image.setScaledContents(True) #图片自适应标签大小
22 
23         lbl_user = QLabel(账号:)  #设置标签
24         lbl_pwd = QLabel(密码:)
25         okbutton = QPushButton(确认)  #设置按钮
26         cancelbutton = QPushButton(取消)
27         lineedit_user = QLineEdit()  #设置单行文本框
28         lineedit_pwd = QLineEdit()
29 
30         grid = QGridLayout()
31         self.setLayout(grid)
32         grid.setSpacing(10)   #间距为10
33 
34         grid.addWidget(lbl_image,1,1,3,1)
35         grid.addWidget(lineedit_user,1,2,1,2)
36         grid.addWidget(lineedit_pwd,2,2,1,2)
37         grid.addWidget(lbl_user,1,4)
38         grid.addWidget(lbl_pwd,2,4)
39         grid.addWidget(okbutton,3,2,1,1)
40         grid.addWidget(cancelbutton,3,3,1,1)
41 
42 if __name__ == __main__:
43     app = QApplication(sys.argv)
44     win = MyWindow()
45     win.show()
46     sys.exit(app.exec_())
跨行跨列示例

显示效果如下:

技术图片

下面来分析代码:

grid.addWidget(lbl_image,1,1,3,1)

 addwidget方法第一个参数是添加的控件对象,后面的(1,1)表示位置坐标为(1,1),即控件左上角坐标为(1,1)。这里的1并不是以像素为单位,而是以行和列为单位,(1,1)即第一行第一列。最后的(3,1)意思是这个控件占三行1列。下面用表格和图片来表示布局方式

图片

(3行1列)

单行文本框1 “账号”标签
单行文本框2 “密码”标签
“确认”按钮 “取消”按钮  
grid.setSpacing(10)

 即各控件之间的上下间距为10(以像素为单位)。同理还有grid.setMargin(int)为设置控件之间的左右间距。


 

以上是关于布局管理(绝对&相对水平垂直格栅表单)的主要内容,如果未能解决你的问题,请参考以下文章

CSS布局--垂直水平居中

Web前端之定位的简介

CSS常见布局问题整理

前端面试题前端布局问题

cocos布局分析

绝对定位元素水平居中和垂直居中的原理