我在我的项目中使用 QGridLayout。我会在 QGridLayout 中自动添加一些小部件。因此,我实现了一个类 MultiWidgetLayout
来管理小部件。我的测试代码是:
import numpy as np
from PyQt5.QtWidgets import *
import sys
class MultiWidgetLayout(QGridLayout):
def __init__(self):
super().__init__()
self.setSpacing(0)
self.setContentsMargins(1,1,1,1)
self.__widgets = []
def getWidgetNum(self):
return len(self.__widgets)
def addWidget(self, widget):
self.__widgets.append(widget)
self.updateLayout()
def setWidgets(self, widgets):
self.__widgets = widgets
self.updateLayout()
def updateLayout(self):
self.removeAllWidgets()
n = len(self.__widgets)
columns = int(np.ceil(np.sqrt(n)))
rows = n//columns
k = 0
for r in range(rows):
for c in range(columns):
super().addWidget(self.__widgets[k], r, c)
k += 1
remain = n - columns*rows
if remain > 0:
for r in range(remain):
super().addWidget(self.__widgets[k], rows, r)
k += 1
for widget in self.__widgets:
widget.show()
def removeAllWidgets(self):
'''
remove all the widgets
'''
N = self.count()
for i in range(N-1,-1,-1):
item = self.itemAt(i) # item is QHBoxLayout
self.removeItem(item)
# self.removeWidget(item)
for widget in self.__widgets:
widget.hide()
class Window(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.setLayout(layout)
self.multiWidgetLayout = MultiWidgetLayout()
self.btn = QPushButton('add widget')
self.btn.clicked.connect(self.addWidgetSlot)
layout.addWidget(self.btn)
layout.addLayout(self.multiWidgetLayout)
def addWidgetSlot(self, check=False):
num = self.multiWidgetLayout.getWidgetNum()
label = QLabel(str(num))
label.setStyleSheet('border: 2px solid red;')
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.multiWidgetLayout.addWidget(label)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
这段代码基本上是我想要的,但是还有一个小问题。
当我添加三个小部件时,布局是:
但是,我希望 QLabel(2) 占据底行的整个空间。
5个小部件的布局是:
但是,我希望 QLable(3) 和 QLabel(4) 占据底行的整个空间。
感谢任何建议!
答案 0 :(得分:1)
由于小部件将具有相似的大小、提示和策略,因此您可以将任何剩余的小部件添加到位于最后一行的水平布局中,跨越所有列。
考虑到没有必要删除小部件并再次添加它们,因为 addWidget()
会自动替换它们在布局中的位置并在需要时重新设置它们的父级,这也使得调用 { {1}}。
这很重要,原因有两个:
show()
覆盖显式的 show()
或 hide()
,这不应该发生);另请注意,setVisible(False)
和 sqrt
已由 ceil
模块提供,该模块是 Python 标准库的一部分。 Numpy 是一个相当大的模块,如果你不需要它用于其他任何东西,你将添加一个重要的要求,它会要求不必要的资源(不仅在内存中,还包括安装,如果不是实际的建设)。
在以下实现中,我使用了 math
来循环浏览所有小部件,因此不需要项目索引。
iter()