布局管理是所有GUI编程中核心内容之一。在Qt里有两种方法可以控制布局,分别是绝对定位和布局类.
代码:
#coding=utf-8
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
class Example1(QWidget):
def __init__(self):
super().__init__()
self.initUI()
pass
def initUI(self):
label1 = QLabel('第一个', self)
label1.move(15, 10)
label2 = QLabel('第2个', self)
label2.move(35, 40)
label3 = QLabel('第3个', self)
label3.move(55, 70)
self.setGeometry(300, 300, 450, 450)
self.setWindowTitle('绝对定位示例')
self.show()
pass
def main1():
app = QApplication(sys.argv)
example1 = Example1()
sys.exit(app.exec_())
if __name__ == '__main__':
main1()
效果:
注意:绝对定位通过move函数进行,相对于父widget的左上角为原点.
箱布局是我们进行布局的首选,核心就是QHBoxLayout和QVBoxLayout。这两个类继承自QBoxLayout,而QBoxLayout
又继承自QLayout
,QLayout
继承自QObject
和QLayoutItem
.
#coding=utf-8
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QPushButton, QHBoxLayout, \
QVBoxLayout
class Example2(QWidget):
def __init__(self):
super().__init__()
self.initUI()
pass
def initUI(self):
okBtn = QPushButton('OK')
cancelBtn = QPushButton('Cancel')
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okBtn)
hbox.addWidget(cancelBtn)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setGeometry(300, 300, 450, 450)
self.setWindowTitle('箱布局')
self.show()
pass
def main2():
app = QApplication(sys.argv)
example2 = Example2()
sys.exit(app.exec_())
if __name__ == '__main__':
main2()
效果:
要点提示
只有一点,那就是addStretch()
函数的理解,它为widget增加一个拉伸因子,至于是怎么拉伸跟父布局有关。如上面代码,就是先拉伸,再添加两个button,所有button会被挤到最右侧。如果我们先添加两个button,再添加这个因子,效果就是这样:
hbox = QHBoxLayout()
hbox.addWidget(okBtn)
hbox.addWidget(cancelBtn)
hbox.addStretch(1)
对应效果:
如果将设置拉伸因子的函数去掉,则添加的两个按钮平分空间,占满整个布局就是这个效果了:
该类继承自QLayout
,也是用的很多。这个可以回想web的布局,早些年一直是表格布局当道。
下面看个计算器的例子:
#coding=utf-8
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QPushButton, QHBoxLayout, \
QVBoxLayout, QGridLayout
class Example3(QWidget):
def __init__(self):
super().__init__()
self.initUI()
pass
def initUI(self):
grid = QGridLayout()
self.setLayout(grid)
names = ['cls', 'bck', '', 'close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
poses = [(i, j) for i in range(5) for j in range(4)]
for pos, name in zip(poses, names):
if name == '':
continue
btn = QPushButton(name)
grid.addWidget(btn, *pos)
self.setGeometry(300, 300, 450, 450)
self.setWindowTitle('网格布局--计算器')
self.show()
pass
def main3():
app = QApplication(sys.argv)
example3 = Example3()
sys.exit(app.exec_())
if __name__ == '__main__':
main3()
效果如下:
核心提示
*pos
的含义,在没有*的时候pos就是(0, 0)是个元组,加个星号之后成了0, 0两个int。QGridLayout还可以设置每个item占多个列,即不均匀分配.
#coding=utf-8
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QPushButton, QHBoxLayout, \
QVBoxLayout, QGridLayout, QLineEdit, QTextEdit
class Example4(QWidget):
def __init__(self):
super().__init__()
self.initUI()
pass
def initUI(self):
title = QLabel('Title')
author = QLabel('Author')
review = QLabel('Review')
titleEdit = QLineEdit()
authorEdit = QLineEdit()
reviewEdit = QTextEdit()
grid = QGridLayout()
grid.setSpacing(30)
grid.addWidget(title, 0, 0)
grid.addWidget(titleEdit, 0, 1)
grid.addWidget(author, 1, 0)
grid.addWidget(authorEdit, 1, 1)
grid.addWidget(review, 2, 0)
grid.addWidget(reviewEdit, 2, 1, 5, 1)
self.setLayout(grid)
self.setGeometry(300, 300, 450, 450)
self.setWindowTitle('网格布局--文本审阅窗口')
self.show()
pass
def main4():
app = QApplication(sys.argv)
example4 = Example4()
sys.exit(app.exec_())
if __name__ == '__main__':
main4()
效果图:
要点提示
1.addWidget的原型
void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = Qt::Alignment())
Places the layout at position (row, column) in the grid. The top-left position is (0, 0).
The alignment is specified by alignment. The default alignment is 0, which means that the widget fills the entire cell.
A non-zero alignment indicates that the layout should not grow to fill the available space but should be sized according to sizeHint().
layout becomes a child of the grid layout
第二个参数是行号,第三个坐标是列号。默认左上角为(0, 0)。
2.addWidget的第二种:
void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())
This is an overloaded function.
This version adds the given widget to the cell grid, spanning multiple rows/columns. The cell will start at fromRow, fromColumn spanning rowSpan rows and columnSpan columns. The widget will have the given alignment.
If rowSpan and/or columnSpan is -1, then the widget will extend to the bottom and/or right edge, respectively.