我的代码由三个类组成:
RoundArt,它创建一个带有圆角的图像;ListWidget,它QListWidget具有某些特征(重要 - 它没有滚动条);MyWindow,它创建应用程序窗口。
在MyWindow我创建一个主容器中,我添加了一个带有滚动条box的垂直容器。box_1
它box_1有4个小部件:
- 铭文
label_1; - 一个小部件
list_widget_1,它是类的副本ListWidget并且是QListWidget; - 铭文
label_2; - 一个小部件
list_widget_2,它是类的副本ListWidget并且是QListWidget.
小部件list_widget_1和list_widget_2我用圆角的图像填充,RoundArt.
我认为box_1拥有一个垂直滚动条将允许小部件list_widget_1既list_widget_2占用他们需要的空间又垂直拉伸——但这并没有发生。内容ListWidget'ов向下移动,不再可见:
我还需要list_widget_1占用list_widget_2尽可能多的空间来正常显示其中的所有元素:
正如我在图片中显示的那样,它list_widget_1占用了所需的空间,其余的小部件(label_2和list_widget_2)向下移动,滚动条允许您查看它们。同时,如果有空闲空间list_widget_1,它们必须保留水平排列元素的能力。list_widget_2请告诉我我该怎么做?
from PyQt5 import QtCore, QtWidgets, QtGui
class RoundArt(QtWidgets.QLabel):
clicked = QtCore.pyqtSignal()
def __init__(self, picture: str, x: int, *args, **kwargs):
super(RoundArt, self).__init__(*args, **kwargs)
self.setFixedSize(x, x)
self.x = x
self.radius = 10
self.setPicture(picture)
def setPicture(self, picture: str):
target = QtGui.QPixmap(self.size())
target.fill(QtCore.Qt.transparent)
p = QtGui.QPixmap(picture).scaled(
self.x, self.x, QtCore.Qt.KeepAspectRatioByExpanding,
QtCore.Qt.SmoothTransformation
)
painter = QtGui.QPainter(target)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform, True)
path = QtGui.QPainterPath()
path.addRoundedRect(0, 0, self.width(), self.height(), self.radius, self.radius)
painter.setClipPath(path)
painter.drawPixmap(0, 0, p)
self.setPixmap(target)
painter.end()
target = None
def mouseReleaseEvent(self, event):
self.clicked.emit()
class ListWidget(QtWidgets.QListWidget):
def __init__(self, *args, **kwargs):
super(ListWidget, self).__init__(*args, **kwargs)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setEditTriggers(self.NoEditTriggers)
self.setDefaultDropAction(QtCore.Qt.IgnoreAction)
self.setSelectionMode(self.ContiguousSelection)
self.setFlow(self.LeftToRight)
self.setWrapping(True)
self.setResizeMode(self.Adjust)
self.setSpacing(14)
self.setContentsMargins(30, 30, 0, 30)
self._rubberPos = None
self._rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
def makeItem(self, lb):
item = QtWidgets.QListWidgetItem(self)
item.setSizeHint(QtCore.QSize(140, 140))
self.setItemWidget(item, lb)
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
scrollArea = QtWidgets.QScrollArea()
content_widget = QtWidgets.QWidget()
scrollArea.setStyleSheet("border-style: hidden;")
scrollArea.setWidget(content_widget)
scrollArea.setWidgetResizable(True)
scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
box_1 = QtWidgets.QVBoxLayout(content_widget)
box = QtWidgets.QHBoxLayout(self)
box.addWidget(scrollArea)
list_widget_1 = ListWidget()
list_widget_2 = ListWidget()
label_1 = QtWidgets.QLabel('label 1')
box_1.addWidget(label_1)
box_1.addWidget(list_widget_1)
label_2 = QtWidgets.QLabel('label 2')
box_1.addWidget(label_2)
box_1.addWidget(list_widget_2)
for i in range(5):
art = RoundArt('album', 150)
list_widget_1.makeItem(art)
for i in range(5):
art = RoundArt('album', 150)
list_widget_2.makeItem(art)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
升级版:
from PyQt5 import QtCore, QtWidgets, QtGui
class RoundArt(QtWidgets.QLabel):
clicked = QtCore.pyqtSignal()
def __init__(self, picture: str, x: int, *args, **kwargs):
super(RoundArt, self).__init__(*args, **kwargs)
self.setFixedSize(x, x)
self.x = x
self.radius = 10
self.setPicture(picture)
def setPicture(self, picture: str):
target = QtGui.QPixmap(self.size())
target.fill(QtCore.Qt.transparent)
p = QtGui.QPixmap(picture).scaled(
self.x, self.x,
QtCore.Qt.KeepAspectRatioByExpanding,
QtCore.Qt.SmoothTransformation
)
painter = QtGui.QPainter(target)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True)
painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform, True)
path = QtGui.QPainterPath()
path.addRoundedRect(0, 0, self.width(), self.height(), self.radius, self.radius)
painter.setClipPath(path)
painter.drawPixmap(0, 0, p)
self.setPixmap(target)
painter.end()
target = None
def mouseReleaseEvent(self, event):
self.clicked.emit()
class ListWidget(QtWidgets.QListWidget):
def __init__(self, *args, **kwargs):
super(ListWidget, self).__init__(*args, **kwargs)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setEditTriggers(self.NoEditTriggers)
self.setDefaultDropAction(QtCore.Qt.IgnoreAction)
self.setSelectionMode(self.ContiguousSelection)
self.setFlow(self.LeftToRight)
self.setWrapping(True)
self.setResizeMode(self.Adjust)
self.setSpacing(10)
#self.setContentsMargins(100, 100, 100, 100)
self._rubberPos = None
self._rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
def makeItem(self, lb):
item = QtWidgets.QListWidgetItem(self)
item.setSizeHint(QtCore.QSize(150, 150))
self.setItemWidget(item, lb)
def updateHeight(self):
self.setMaximumHeight(self.sizeHint().height())
def getHeight(self, parent=None):
height = 0
if not parent:
parent = self.rootIndex()
for row in range(self.model().rowCount(parent)):
child = self.model().index(row, 0, parent)
height += 150
return height
def sizeHint(self):
hint = super().sizeHint()
hint.setHeight(self.getHeight())
return hint
def minimumSizeHint(self):
return self.sizeHint()
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.dict = {} # словарь для хранения QListWidget'ов и количества изображений внутри них
scrollArea = QtWidgets.QScrollArea()
content_widget = QtWidgets.QWidget()
#scrollArea.setStyleSheet("border-style: hidden;")
scrollArea.setWidget(content_widget)
scrollArea.setWidgetResizable(True)
scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.box_1 = QtWidgets.QVBoxLayout(content_widget)
box = QtWidgets.QHBoxLayout(self)
box.addWidget(scrollArea)
self.list_widget_1 = ListWidget()
self.list_widget_2 = ListWidget()
self.label_1 = QtWidgets.QLabel('label 1')
self.box_1.addWidget(self.label_1)
self.box_1.addWidget(self.list_widget_1, stretch = 1)
label_2 = QtWidgets.QLabel('label 2')
self.box_1.addWidget(label_2)
self.box_1.addWidget(self.list_widget_2, stretch=1)
self.box_1.addStretch(100)
a = 11 # любое число, позже программа будет получать его самостоятельно
for i in range(a):
art = RoundArt('album.png', 150)
self.list_widget_1.makeItem(art)
self.dict[self.list_widget_1] = a
b = 5 # любое число, позже программа будет получать его самостоятельно
for i in range(b):
art = RoundArt('album.png', 150)
self.list_widget_2.makeItem(art)
self.dict[self.list_widget_2] = b
def resizeEvent(self, event):
l = 150 # размер стороны изображения
d = 10 # отступ между изображениями
m = l + 2*d
for widget in self.dict:
n = self.dict[widget] # количество изображений
k = (widget.width() - 4.5)//m
if n % k == 0:
h = m*(n // k) + 4
else:
h = m*(n // k + 1) + 4
widget.setMinimumHeight(h)
self.update()
super(MyWindow, self).resizeEvent(event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())


我可能在调试、实验时写了一些多余的东西,如果你发现一些不必要的东西,删除或更正它。祝你好运。
更新
我检查了您在更新中发布的几个选项的示例(我没有检查计算逻辑)。我唯一发现的是,在加载应用程序时,窗口显示不正确,但调整窗口大小显示正确。
我建议像这样修复它: