一、布局概念与方式
1、布局概念:布局就是指按照某种规则将子控件摆在父控件中。
2、布局方式:
1 from PyQt5.Qt import * 2 3 class Window(QWidget): 4 def __init__(self): 5 super().__init__() 6 self.setWindowTitle("布局管理") 7 self.resize(500, 500) 8 self.setup_ui() 9 10 def setup_ui(self): 11 label1 = QLabel("标签1",self) 12 label1.setStyleSheet("background-color:cyan") 13 label2 = QLabel("标签2", self) 14 label2.setStyleSheet("background-color:yellow") 15 label3 = QLabel("标签3", self) 16 label3.setStyleSheet("background-color:red") 17 18 # 普通方法 19 # label_widdth = self.width() 20 # label_height = self.height()/3 21 # label1.resize(label_widdth,label_height) 22 # label2.resize(label_widdth,label_height) 23 # label3.resize(label_widdth,label_height) 24 25 # label1.move(0,0) 26 # label2.move(0,1*label_height) 27 # label3.move(0,2*label_height) 28 29 30 # 布局管理方式实现 31 v_layout = QVBoxLayout() 32 v_layout.addWidget(label1) 33 v_layout.addWidget(label2) 34 v_layout.addWidget(label3) 35 36 self.setLayout(v_layout) 37 label2.hide() # 缺少标签2,内容也会自动调整 38 39 40 if __name__ == '__main__': 41 import sys 42 43 app=QApplication(sys.argv) 44 45 window=Window() 46 window.show() 47 sys.exit(app.exec_())
3、布局管理器概念
4、布局的简单使用演示
1 # 使用演示 2 label1 = QLabel("标签1") 3 label1.setStyleSheet("background-color:cyan") 4 label2 = QLabel("标签2") 5 label2.setStyleSheet("background-color:yellow") 6 label3 = QLabel("标签3") 7 label3.setStyleSheet("background-color:red") 8 9 v_layout = QHBoxLayout() # 水平方向 10 v_layout.addWidget(label1) 11 v_layout.addWidget(label2) 12 v_layout.addWidget(label3) 13 14 v_layout.setContentsMargins(20, 30, 40, 50) # 设置内容的外边距 15 v_layout.setSpacing(30) # 内容与内容之间 16 17 self.setLayoutDirection(Qt.RightToLeft) # 从右到左排序(上面标签) 18 19 self.setLayout(v_layout) 20 21 print(self.children())
二、布局管理器的详细使用
1、基类
(1)基类-QLayout
(2)基类-QBoxLayout的功能作用
由于基类的QBoxLayout就是QLayout的子类,因此就一起分析实现。
1 # *******************基类**********************开始 2 from PyQt5.Qt import * 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("基类-QLayout") 8 self.resize(500, 500) 9 self.setup_ui() 10 11 def setup_ui(self): 12 label1 = QLabel("标签1") 13 label1.setStyleSheet("background-color:cyan") 14 label2 = QLabel("标签2") 15 label2.setStyleSheet("background-color:yellow") 16 label3 = QLabel("标签3") 17 label3.setStyleSheet("background-color:red") 18 19 # 1、传建一个布局管理器对象 20 # layout = QBoxLayout(QBoxLayout.RightToLeft) # 从右到左 21 layout = QBoxLayout(QBoxLayout.BottomToTop) # 从从下到上 22 '''(self, QBoxLayout_Direction, parent=None)''' 23 # 2、直接把布局管理对象设置给需要布局的父控件 24 self.setLayout(layout) 25 # 3、把需要布局的子控件添加到布局管理器中 26 # layout.addWidget(label1) 27 # layout.addWidget(label2) 28 # layout.addWidget(label3) 29 30 # 设置控件之间的间距 31 layout.setSpacing(20) 32 33 # 设置外边距 34 print(layout.contentsMargins().left()) # 查看左边间距 35 print(layout.contentsMargins().right()) # 查看右边间距 36 # layout.setContentsMargins(20,20,20,20) # (左上右下)修改 37 38 # 替换子控件 39 # label4 = QLabel("标签4") 40 # label4.setStyleSheet("background-color:orange") 41 # layout.replaceWidget(label2,label4) # 被替换的控件需要隐藏掉 42 # # label2.hide() # 隐藏,并没有释放掉 43 # label2.setParent(None) # 控件没有父对象就会被释放掉(删除一个控件的办法) 44 45 # 添加子布局(布局的嵌套) 46 label5 = QLabel("标签5") 47 label5.setStyleSheet("background-color:pink") 48 label6 = QLabel("标签6") 49 label6.setStyleSheet("background-color:blue") 50 label7 = QLabel("标签7") 51 label7.setStyleSheet("background-color:green") 52 53 h_layout = QBoxLayout(QBoxLayout.LeftToRight) 54 h_layout.addWidget(label5) 55 h_layout.addWidget(label6) 56 h_layout.addWidget(label7) 57 58 # 3、把需要布局的子控件添加到布局管理器中 59 layout.addWidget(label1) 60 layout.addLayout(h_layout) 61 layout.addWidget(label2) 62 layout.addWidget(label3) 63 64 # 能用性 65 layout.setEnabled(False) # 布局管理器失效 66 67 68 if __name__ == '__main__': 69 import sys 70 71 app=QApplication(sys.argv) 72 73 window=Window() 74 window.show() 75 sys.exit(app.exec_()) 76 # *******************基类**********************结束
1 # *******************基类-QBoxLayout**********************开始 2 from PyQt5.Qt import * 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("类-QBoxLayout") 8 self.resize(500, 500) 9 self.setup_ui() 10 11 def setup_ui(self): 12 label1 = QLabel("标签1") 13 label1.setStyleSheet("background-color:cyan") 14 label2 = QLabel("标签2") 15 label2.setStyleSheet("background-color:yellow") 16 label3 = QLabel("标签3") 17 label3.setStyleSheet("background-color:red") 18 label4 = QLabel("标签4") 19 label4.setStyleSheet("background-color:orange") 20 21 # 1、创建布局管理器对象 22 layout = QBoxLayout(QBoxLayout.LeftToRight) 23 # 2、把布局管理器对象设置给需要布局的父控件 24 self.setLayout(layout) 25 # # 3、添加需要布局的子控件到布局管理器中 26 # layout.addWidget(label1) 27 # 28 # 添加空白(空白盒子,方便布局) 29 # layout.addSpacing(40) 30 31 # layout.addWidget(label2) 32 # layout.addWidget(label3) 33 # layout.addWidget(label4) 34 35 # 修改方向 36 # timer = QTimer(self) 37 # def test(): 38 # layout.setDirection((layout.direction()+1)%4) # 0--3之间循环,不同值代表不同方向(类属性值) 39 # timer.timeout.connect(test) 40 # timer.start(1000) 41 42 # 添加元素(也可以插入布局insertLayout) 43 # layout.insertWidget(1,label4) # 1代表位置 44 45 # 移除控件 46 # layout.removeWidget(label1) # 也只是从布局管理器中移除,本身还是在 47 48 # 插入空白 49 # layout.insertSpacing(4,30) 50 51 # 添加伸缩(弹簧) 52 layout.addWidget(label1,1) 53 layout.addStretch(2) # 空白伸缩因子,可以压缩到没有 54 layout.addWidget(label2,1) 55 layout.addStretch(2) 56 layout.addWidget(label3,1) 57 # layout.addWidget(label4) 58 59 layout.setStretchFactor(label2,2) # 给标签2设置伸缩因子(也可以给子布局设置) 60 61 if __name__ == '__main__': 62 import sys 63 64 app=QApplication(sys.argv) 65 66 window=Window() 67 window.show() 68 sys.exit(app.exec_()) 69 # *******************基类-QBoxLayout**********************结束
2、QHBoxLayout与QVBoxLayout
3、QFormLayout表单布局
(1)构造函数
(2)行操作
1 from PyQt5.Qt import * 2 3 class Window(QWidget): 4 def __init__(self): 5 super().__init__() 6 self.setWindowTitle("QFormLayout") 7 self.resize(500, 500) 8 self.setup_ui() 9 10 def setup_ui(self): 11 # name_label = QLabel("姓名(&n):") 12 # age_label = QLabel("年龄(&g):") 13 sex_label = QLabel("性别") 14 15 name_le = QLineEdit() 16 age_sb = QSpinBox() 17 18 submit_btn = QPushButton("提交") 19 male_rb = QRadioButton("男") 20 female_rb = QRadioButton("女") 21 22 # 添加小伙伴 23 # name_label.setBuddy(name_le) 24 # age_label.setBuddy(age_sb) 25 26 # 性别布局 27 h_layout = QHBoxLayout() 28 h_layout.addWidget(male_rb) 29 h_layout.addWidget(female_rb) 30 31 # 1、创建布局管理器 32 layout = QFormLayout() 33 # 2、把布局管理器赋值给需要布局的父控件 34 self.setLayout(layout) 35 # 3、把需要布局的子控件交给布局管理器进行布局 36 # layout.addWidget(name_lable) 37 # layout.addWidget(name_le) 38 # layout.addRow(name_label,name_le) # 行操作 39 layout.addRow("姓名(&n)",name_le) # 行操作实现创建姓名标签与小伙伴 40 layout.addRow(sex_label,h_layout) # 行操作-添加子布局 41 # layout.addRow(age_label,age_sb) 42 layout.addRow("年龄(&g)",age_sb) # 行操作实现创建年龄标签与小伙伴 43 layout.addRow(submit_btn) 44 45 if __name__ == '__main__': 46 import sys 47 48 app=QApplication(sys.argv) 49 50 window=Window() 51 window.show() 52 sys.exit(app.exec_())
1 from PyQt5.Qt import * 2 3 class Window(QWidget): 4 def __init__(self): 5 super().__init__() 6 self.setWindowTitle("QFormLayout") 7 self.resize(500, 500) 8 self.setup_ui() 9 10 def setup_ui(self): 11 name_le = QLineEdit() 12 age_sb = QSpinBox() 13 14 submit_btn = QPushButton("提交") 15 male_rb = QRadioButton("男") 16 female_rb = QRadioButton("女") 17 18 # 性别布局 19 h_layout = QHBoxLayout() 20 h_layout.addWidget(male_rb) 21 h_layout.addWidget(female_rb) 22 23 # 1、创建布局管理器 24 layout = QFormLayout() 25 # 2、把布局管理器赋值给需要布局的父控件 26 self.setLayout(layout) 27 # 3、把需要布局的子控件交给布局管理器进行布局 28 # layout.addRow("姓名(&n)",name_le) # 行操作实现创建姓名标签与小伙伴 29 # layout.addRow("年龄(&g)",age_sb) # 行操作实现创建年龄标签与小伙伴 30 # layout.addRow(submit_btn) 31 # 插入行 32 # layout.insertRow(1,"性别:",h_layout) 33 34 # 获取行 35 # print(layout.rowCount()) 36 # print(layout.getWidgetPosition(age_sb)) 37 # print(layout.getLayoutPosition(h_layout)) 38 39 # 修改行 40 name_label = QLabel("姓名:") 41 layout.setWidget(0,QFormLayout.LabelRole,name_label) # 作边添加标签角色 42 layout.setWidget(0,QFormLayout.FieldRole,name_le) # 右边添加文本角色 43 44 45 if __name__ == '__main__': 46 import sys 47 48 app=QApplication(sys.argv) 49 50 window=Window() 51 window.show() 52 sys.exit(app.exec_())
1 from PyQt5.Qt import * 2 3 class Window(QWidget): 4 def __init__(self): 5 super().__init__() 6 self.setWindowTitle("QFormLayout") 7 self.resize(500, 500) 8 self.setup_ui() 9 10 def setup_ui(self): 11 sex_label = QLabel("性别:") 12 name_le = QLineEdit() 13 age_sb = QSpinBox() 14 15 submit_btn = QPushButton("提交") 16 male_rb = QRadioButton("男") 17 female_rb = QRadioButton("女") 18 19 # 性别布局 20 h_layout = QHBoxLayout() 21 h_layout.addWidget(male_rb) 22 h_layout.addWidget(female_rb) 23 24 # 1、创建布局管理器 25 layout = QFormLayout() 26 # 2、把布局管理器赋值给需要布局的父控件 27 self.setLayout(layout) 28 # 3、把需要布局的子控件交给布局管理器进行布局 29 layout.addRow("姓名(&n)",name_le) # 行操作实现创建姓名标签与小伙伴 30 layout.addRow("年龄(&g)",age_sb) # 行操作实现创建年龄标签与小伙伴 31 layout.addRow(sex_label,h_layout) 32 layout.addRow(submit_btn) 33 34 # 移除行 35 # layout.removeRow(1) # 移除第二行控件(但是没有释放) 36 # layout.removeWidget(sex_label) # 移除某一控件 37 # layout.takeRow(1) # 拿走第二个控件,影响布局 38 39 # 标签操作:修改名字样式(姓名——name) 40 print(layout.labelForField(name_le)) # 拿到QLabel对象 41 layout.labelForField(name_le).setText('name') # 修改标签 42 43 44 if __name__ == '__main__': 45 import sys 46 47 app=QApplication(sys.argv) 48 49 window=Window() 50 window.show() 51 sys.exit(app.exec_())
(3)行的包装策略
1 # 行的包装策略 2 # layout.setRowWrapPolicy(QFormLayout.WrapAllRows) # 文本始终位于标签下面 3 layout.setRowWrapPolicy(QFormLayout.WrapLongRows) # 标签不变,文本若是放不下,自动跳转到下一行
(4)对齐方式
1 # 对齐方式 2 print(layout.formAlignment() == Qt.AlignLeft | Qt.AlignTop) # True 3 # layout.setFormAlignment(Qt.AlignLeft | Qt.AlignBottom) # 左对齐+底部对齐 4 layout.setLabelAlignment(Qt.AlignCenter) # 居中对齐间距
(5)间距
1 # 间距 2 layout.setVerticalSpacing(40) # 垂直方向间距 3 layout.setHorizontalSpacing(40) # 水平方向间距
(6)字段增长策略
1 # 字段增长策略 2 layout.setFieldGrowthPolicy(QFormLayout.FieldsStayAtSizeHint) # 保持原样不跟着改变
4、QGridLayout网格布局
(1)构造函数
(2)元素操作
1 from PyQt5.Qt import * 2 3 class Window(QWidget): 4 def __init__(self): 5 super().__init__() 6 self.setWindowTitle("QGridLayout") 7 self.resize(500, 500) 8 self.setup_ui() 9 10 def setup_ui(self): 11 gl = QGridLayout() 12 self.setLayout(gl) 13 label1 = QLabel("标签1") 14 label1.setStyleSheet("background-color:cyan") 15 label2 = QLabel("标签2") 16 label2.setStyleSheet("background-color:yellow") 17 label3 = QLabel("标签3") 18 label3.setStyleSheet("background-color:green") 19 20 label4 = QLabel("标签4") 21 label4.setStyleSheet("background-color:blue") 22 label5 = QLabel("标签5") 23 label5.setStyleSheet("background-color:red") 24 label6 = QLabel("标签6") 25 label6.setStyleSheet("background-color:pink") 26 27 # 元素操作 28 gl.addWidget(label1,0,0) 29 gl.addWidget(label2,0,1) 30 # gl.addWidget(label3,1,0,1,2) # 从第1行的第0列开始,合并1行2列 31 gl.addWidget(label3,1,0,2,2) # 从第1行的第0列开始,合并1行2列 32 33 layout = QVBoxLayout() 34 layout.addWidget(label4) 35 layout.addWidget(label5) 36 layout.addWidget(label6) 37 gl.addLayout(layout,3,0,1,3) # 添加子布局 38 39 print(gl.getItemPosition(0)) # 标签1的位置及所占大小 40 print(gl.getItemPosition(2)) # 标签3的位置及所占大小 41 print(gl.itemAtPosition(0,1).widget().text()) # 查看某个位置是什么标签 42 43 if __name__ == '__main__': 44 import sys 45 46 app=QApplication(sys.argv) 47 48 window=Window() 49 window.show() 50 sys.exit(app.exec_())
(3)列宽/行高和拉伸系数
1 # 列宽/行高和拉伸系数 2 # gl.setColumnMinimumWidth(0,100) # 设置标签1的最小宽度100 3 # gl.setRowMinimumHeight(0,100) # 设置第0行的最小高度为100 4 5 gl.setColumnStretch(0, 2) # 第0列拉伸系数为2 6 gl.setColumnStretch(1, 1) # 第2列拉伸系数为1 7 8 gl.setRowStretch(3, 1)
(4)间距
1 # 间距 2 print(gl.spacing()) 3 # gl.setVerticalSpacing(20) # 行与行之间间距设置 4 # gl.setHorizontalSpacing(20) # 行与行之间间距设置 5 gl.setSpacing(60) # 统一设置
(5)原点角
1 # 原点角 2 gl.setOriginCorner(Qt.TopRightCorner) # 原点角位于右上角 3 gl.setOriginCorner(Qt.BottomLeftCorner) # 原点角位于左上角
(6)信息获取
1 # 信息获取 2 print(gl.rowCount()) 3 print(gl.columnCount()) 4 5 # 注意cellRect的获取 6 gl = window.layout() 7 print(gl.cellRect(0, 0))
5、QStackedLayout堆叠布局
# *******************QStackedLayout**********************开始 from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QStackedLayout") self.resize(500, 500) self.setup_ui() def setup_ui(self): # 1、创建一个布局管理器对象 sl = QStackedLayout() # 2、把布局随想设置给要布局的父控件(父布局) self.setLayout(sl) # 此项建议放在添加子控件之前 # 3、通过布局对象,管理布局一些子控件 label1 = QLabel("标签1") label1.setStyleSheet("background-color:cyan") label2 = QLabel("标签2") label2.setStyleSheet("background-color:yellow") label3 = QLabel("标签3") label3.setStyleSheet("background-color:green") label4 = QLabel("标签4") label4.setStyleSheet("background-color:blue") label5 = QLabel("标签5") label5.setStyleSheet("background-color:red") label6 = QLabel("标签6") label6.setStyleSheet("background-color:pink") v_layout = QVBoxLayout() v_layout.addWidget(label4) v_layout.addWidget(label5) v_layout.addWidget(label6) sl.addWidget(label1) sl.addWidget(label2) sl.addWidget(label3) sl.insertWidget(1,label4) # 通过索引值来指定展示的标签 # sl.setCurrentIndex(2) # timer = QTimer(self) # timer.timeout.connect(lambda :sl.setCurrentIndex((sl.currentIndex()+1)%sl.count())) # timer.start(1000) # 信号-currentChanged # sl.currentChanged.connect(lambda val:print(val)) # 展示模式 sl.setStackingMode(QStackedLayout.StackAll) # 所有小部件可见(默认是不可见),只展示一个 label1.hide() # 信号- sl.widgetRemoved.connect(lambda :print("控件被移除")) sl.removeWidget(label2) if __name__ == '__main__': import sys app=QApplication(sys.argv) window=Window() window.show() sys.exit(app.exec_()) # *******************QStackedLayout**********************结束
三、布局管理补充--尺寸策略
1、QWidget.sizeHint( )
2、QWidget.minimumSizeHint( )
3、控件的尺寸策略
(1)作用
(2)使用方式
1 # *******************布局管理的补充-尺寸策略**********************开始 2 from PyQt5.Qt import * 3 4 class Label(QLabel): 5 # def minimumSizeHint(self): 6 # return QSize(200,200) 7 8 def sizeHint(self): 9 return QSize(150,60) 10 11 class Window(QWidget): 12 def __init__(self): 13 super().__init__() 14 self.setWindowTitle("补充-尺寸策略") 15 self.resize(500, 500) 16 self.setup_ui() 17 18 def setup_ui(self): 19 # label1 = QLabel("标签1") 20 label1 = Label("标签1") # 自定义建议大小,并返回 21 label1.setStyleSheet("background-color:cyan") 22 label2 = QLabel("标签2") 23 label2.setStyleSheet("background-color:yellow") 24 label3 = QLabel("标签3") 25 label3.setStyleSheet("background-color:green") 26 27 layout = QVBoxLayout() 28 self.setLayout(layout) 29 layout.addWidget(label1) 30 layout.addWidget(label2) 31 layout.addWidget(label3) 32 33 # 尺寸策略 34 # label1.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed) # 尺寸策略,固定label1的尺寸 35 # label1.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Maximum) # 尺寸策略,固定水平,垂直不能超过建议的最大值 36 # label1.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Preferred) # 标签1优先 37 # label2.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding) 38 sp = QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Ignored) 39 sp.setRetainSizeWhenHidden(True) # 保留标签1隐藏的控件 40 label1.setSizePolicy(sp) 41 42 label1.hide() 43 44 label2.setFixedSize(200,200) # 固定标签2的尺寸,无论什么策略,固定的级别最高 45 46 if __name__ == '__main__': 47 import sys 48 49 app=QApplication(sys.argv) 50 51 window=Window() 52 window.show() 53 sys.exit(app.exec_()) 54 # *******************布局管理的补充-尺寸策略**********************结束