一、绝对布局
每个程序都是以像素为单位区分元素的位置,衡量元素的大小。所以我们完全可以使用绝对定位搞定每个元素和窗口的位置。
比如,我们想要设计下面这一个布局。
代码如下:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
#主界面的属性
self.setGeometry(90, 90, 600, 300)#从屏幕上左上角(90,90)开始,显示一个1024*768的界面
self.setWindowTitle('绝对布局测试程序')#主界面标题栏
button1 = QPushButton('第一个button', self)
button1.move(0, 0) #button位置(左上角坐标)
button1.resize(100, 50) #button大小
button2 = QPushButton('第二个button', self)
button2.move(100, 50) # button位置(左上角坐标)
button2.resize(100, 50) # button大小
button3 = QPushButton('第三个button', self)
button3.move(200, 100) # button位置(左上角坐标)
button3.resize(100, 50) # button大小
button4 = QPushButton('第四个button', self)
button4.move(300, 150) # button位置(左上角坐标)
button4.resize(100, 50) # button大小
button5 = QPushButton('第五个button', self)
button5.move(400, 200) # button位置(左上角坐标)
button5.resize(100, 50) # button大小
button6 = QPushButton('第六个button', self)
button6.move(500, 250) # button位置(左上角坐标)
button6.resize(100, 50) # button大小
self.show()#显示窗口
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
其中,
self.setGeometry(90, 90, 600, 300)#从屏幕上左上角(90,90)开始,显示一个1024*768的界面
self.setWindowTitle('绝对布局测试程序')#主界面标题栏
是比较常用的两个函数。
设计过程中我们可以看到绝对布局的局限性:
- 元素不会随着我们更改窗口的位置和大小而变化。
- 不能适用于不同的平台和不同分辨率的显示器
- 更改应用字体大小会破坏布局
- 如果我们决定重构这个应用,需要全部计算一下每个元素的位置和大小
二、盒布局。
盒布局名字虽然听起来怪怪的,但是却非常形象,主要借助两个函数QHBoxLayout
(水平方向)和QVBoxLayout
(竖直方向),建立一个个水平方向或者是竖直方向的“盒子”,盒子本身整齐排列,同时把盒子内部的组件也整齐排列,这样整体来看就显得会很整齐。就像小时候写作业一样,放置内容之前之间先给你把区域划好了。
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication,QMainWindow)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 添加5个按钮
Button1 = QPushButton("按钮1")
Button2 = QPushButton("按钮2")
Button3 = QPushButton("按钮3")
Button4 = QPushButton("按钮4")
Button5 = QPushButton("按钮5")
#添加一个竖直盒子,两个水平盒子
hbox1 = QHBoxLayout()
hbox2 = QHBoxLayout()
# hbox = QHBoxLayout()
vbox = QVBoxLayout()
#把按钮放在盒子里
vbox.addWidget(Button1)
vbox.addWidget(Button2)
vbox.addWidget(Button3)
hbox2.addWidget(Button4)
hbox2.addWidget(Button5)
#把竖直盒子和水平盒子嵌套在水平盒子中
hbox1.addLayout(vbox)
hbox1.addLayout(hbox2)
self.setLayout(hbox1)
self.setGeometry(400, 400, 600, 300)
self.setWindowTitle('盒布局示例')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
效果如下:
最后,在盒布局里,还有一个特别有用的函数:布局.addStretch(int)
。这个函数很形象,就是在布局之内添加一个弹簧,使组件之间有空隙。int值代表“弹簧”的长度。
在QT Designer中,你可以看到这个组件就是一个弹簧样子的。
需要注意的是:弹簧控件是按照这个弹簧的比例分的,比如:
hbox.addStretch(1)#hbox是一个水平“盒子”
hbox.addWidget(Button1)
hbox.addStretch(1)
hbox.addWidget(Button2)
hbox.addStretch(1)
就是把hbox
这个盒子剩余空间等分成三份,如果把中间的弹簧改成2,那么就是把这个盒子剩余空间等分成4分,中间的空间占两份。对比如下:
下面,我们接着上边的代码,添加几个“弹簧”。使布局更为宽松一点。(虽然只改动了几行,为了方便调试,还是附上整体的代码,读者可以把代码复制到自己的环境中,调整各个弹簧的比例看看效果)
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication,QMainWindow)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 添加5个按钮
Button1 = QPushButton("按钮1")
Button2 = QPushButton("按钮2")
Button3 = QPushButton("按钮3")
Button4 = QPushButton("按钮4")
Button5 = QPushButton("按钮5")
#添加一个竖直盒子,两个水平盒子
hbox1 = QHBoxLayout()
hbox2 = QHBoxLayout()
# hbox = QHBoxLayout()
vbox = QVBoxLayout()
#把按钮放在盒子里
vbox.addStretch(2)#比重为2的弹簧
vbox.addWidget(Button1)
vbox.addStretch(1)#比重为1的弹簧
vbox.addWidget(Button2)
vbox.addStretch(1)#比重为1的弹簧
vbox.addWidget(Button3)
vbox.addStretch(2)#比重为2的弹簧
hbox2.addStretch(1)#比重为1的弹簧
hbox2.addWidget(Button4)
hbox2.addStretch(1)#比重为1的弹簧
hbox2.addWidget(Button5)
hbox2.addStretch(1)#比重为1的弹簧
#把竖直盒子和水平盒子嵌套在水平盒子中
hbox1.addLayout(vbox)
hbox1.addLayout(hbox2)
self.setLayout(hbox1)
self.setGeometry(400, 400, 600, 300)
self.setWindowTitle('盒布局示例')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
效果如下:
三、网格布局。
这种布局就是把窗口分成一个个小的网格。创建和使用网格布局,需要使用QGridLayout模块。就像前几年在父母辈流行的十字绣一样,通过一个个小网格来定位组件的位置和大小。
这种布局好处是整齐划一,如棋盘格一样,缺点也很明显:布局太过刻板。这里不多介绍。
一些小的技巧
- 固定窗口大小,加入如下代码:
self.setFixedSize(self.width,self.height)
。这样窗口就不能随意放大缩小了。(在QT Designer中,在主界面右击鼠标,选择“大小限定”,就可以限制界面的最大(小)宽度和高度)
总结:
可以看到,若只是设计一个自己使用的,功能简单的基本界面,那么绝对布局+固定窗口大小也是可以凑合的;若是希望简单的控件水平或竖直排列,使用QHBoxLayout和QVBoxLayout更加方便,QGridLayout适合较为整齐方正的界面布局。
最后,可能大家注意到了,我对布局的很多函数并没有过多说明,因为就算费劲学了这么多函数,但即使是搭建一个简单的前端界面,通过代码搭建也是很耗费时间的,简直吃力不讨好。就拿盒布局来说,简单的几个组件,需要三个盒子来承载,而且还需要调节“弹簧”的比例,非常麻烦。
所以,我们只需要通过这几个简单的代码来掌握pyqt布局的基本知识,在实际开发中更推荐利用QT Designer来可视化来搭建前端,这种搭建前端的方式上手简单,方式快捷,简直是居家旅行必备,老少皆宜的……唉不好意思走错片场了。
反正实际经验来说,使用可视化的方法开发前端,真是省时又省力,完全可以用十分钟左右的时间搭建一个基本的界面。
pycharm中配置QT Designer的方法见:python+pycharm+pyqt5+QT Designer前端开发完整配置攻略 。
QT Designer的使用也很简单,在掌握了基本的布局和组件的作用之后,打开這个界面玩一玩,试着像搭积木一样搭一个简单的界面,玩着玩着就学会了。
扩展阅读:
使用Qt Designer来设计界面