Перенос виджетов при изменении размеров окна
Есть несколько QScrollArea. Необходимо, чтобы при изменении размера главного окна совершался перенос виджетов, как переносится текст в QTextEdit.
Не совсем понятно через что добиться такого поведения. Переписывать QHBoxLayout и добавлять код из QVBoxLayout?
Или же переписывать какой-нибудь виджет и уже в него встраивать QScrollArea?
Видел подобную реализацию на основе QTabBar, но думаю, что в этом случае писать придётся ещё больше.
Несколько QScrollArea:
Желаемое поведение при уменьшении размеров окна:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.horizontalLayout_16 = QtWidgets.QHBoxLayout(self.centralwidget)
self.scrollArea_2 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_9 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_9.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_9)
self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_9)
self.horizontalLayout_9.addWidget(self.label_2)
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_9)
self.horizontalLayout_16.addWidget(self.scrollArea_2)
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_8 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_8.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_8)
self.label_6 = QtWidgets.QLabel(self.scrollAreaWidgetContents_8)
self.horizontalLayout_8.addWidget(self.label_6)
self.scrollArea.setWidget(self.scrollAreaWidgetContents_8)
self.horizontalLayout_16.addWidget(self.scrollArea)
self.scrollArea_3 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_10 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_10.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_10)
self.label_9 = QtWidgets.QLabel(self.scrollAreaWidgetContents_10)
self.horizontalLayout_10.addWidget(self.label_9)
self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_10)
self.horizontalLayout_16.addWidget(self.scrollArea_3)
self.scrollArea_4 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_11 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_11.setGeometry(QtCore.QRect(0, 0, 77, 200))
self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_11)
self.label_14 = QtWidgets.QLabel(self.scrollAreaWidgetContents_11)
self.horizontalLayout_11.addWidget(self.label_14)
self.scrollArea_4.setWidget(self.scrollAreaWidgetContents_11)
self.horizontalLayout_16.addWidget(self.scrollArea_4)
self.scrollArea_7 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_14 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_14.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_14)
self.label_15 = QtWidgets.QLabel(self.scrollAreaWidgetContents_14)
self.horizontalLayout_12.addWidget(self.label_15)
self.scrollArea_7.setWidget(self.scrollAreaWidgetContents_14)
self.horizontalLayout_16.addWidget(self.scrollArea_7)
self.scrollArea_8 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_15 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_15.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_15)
self.label_16 = QtWidgets.QLabel(self.scrollAreaWidgetContents_15)
self.horizontalLayout_13.addWidget(self.label_16)
self.scrollArea_8.setWidget(self.scrollAreaWidgetContents_15)
self.horizontalLayout_16.addWidget(self.scrollArea_8)
self.scrollArea_6 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_13 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_13.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_13)
self.label_17 = QtWidgets.QLabel(self.scrollAreaWidgetContents_13)
self.horizontalLayout_14.addWidget(self.label_17)
self.scrollArea_6.setWidget(self.scrollAreaWidgetContents_13)
self.horizontalLayout_16.addWidget(self.scrollArea_6)
self.scrollArea_5 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_12 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_12.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_12)
self.label_18 = QtWidgets.QLabel(self.scrollAreaWidgetContents_12)
self.horizontalLayout_15.addWidget(self.label_18)
self.scrollArea_5.setWidget(self.scrollAreaWidgetContents_12)
self.horizontalLayout_16.addWidget(self.scrollArea_5)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
self.label_2.setText(_translate("MainWindow", "Окно 1"))
self.label_6.setText(_translate("MainWindow", "Окно 2"))
self.label_9.setText(_translate("MainWindow", "Окно 3"))
self.label_14.setText(_translate("MainWindow", "Окно 4"))
self.label_15.setText(_translate("MainWindow", "Окно 5"))
self.label_16.setText(_translate("MainWindow", "Окно 6"))
self.label_17.setText(_translate("MainWindow", "Окно 7"))
self.label_18.setText(_translate("MainWindow", "Окно 8"))
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
Ответы (2 шт):
Вот вам простенький вариант того что вы хотите. Я поэкспериментировал с "Окно 1" и "Окно 2".
Обратите внимание, что изменил ОДНУ строку в вашей форме. Пробуйте.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
# self.horizontalLayout_16 = QtWidgets.QHBoxLayout(self.centralwidget) # ---
self.horizontalLayout_16 = QtWidgets.QHBoxLayout() # +++
self.scrollArea_2 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_9 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_9.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_9)
self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_9)
self.horizontalLayout_9.addWidget(self.label_2)
self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_9)
self.horizontalLayout_16.addWidget(self.scrollArea_2)
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_8 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_8.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_8)
self.label_6 = QtWidgets.QLabel(self.scrollAreaWidgetContents_8)
self.horizontalLayout_8.addWidget(self.label_6)
self.scrollArea.setWidget(self.scrollAreaWidgetContents_8)
self.horizontalLayout_16.addWidget(self.scrollArea)
self.scrollArea_3 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_10 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_10.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_10)
self.label_9 = QtWidgets.QLabel(self.scrollAreaWidgetContents_10)
self.horizontalLayout_10.addWidget(self.label_9)
self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_10)
self.horizontalLayout_16.addWidget(self.scrollArea_3)
self.scrollArea_4 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_11 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_11.setGeometry(QtCore.QRect(0, 0, 77, 200))
self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_11)
self.label_14 = QtWidgets.QLabel(self.scrollAreaWidgetContents_11)
self.horizontalLayout_11.addWidget(self.label_14)
self.scrollArea_4.setWidget(self.scrollAreaWidgetContents_11)
self.horizontalLayout_16.addWidget(self.scrollArea_4)
self.scrollArea_7 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_14 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_14.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_14)
self.label_15 = QtWidgets.QLabel(self.scrollAreaWidgetContents_14)
self.horizontalLayout_12.addWidget(self.label_15)
self.scrollArea_7.setWidget(self.scrollAreaWidgetContents_14)
self.horizontalLayout_16.addWidget(self.scrollArea_7)
self.scrollArea_8 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_15 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_15.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_15)
self.label_16 = QtWidgets.QLabel(self.scrollAreaWidgetContents_15)
self.horizontalLayout_13.addWidget(self.label_16)
self.scrollArea_8.setWidget(self.scrollAreaWidgetContents_15)
self.horizontalLayout_16.addWidget(self.scrollArea_8)
self.scrollArea_6 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_13 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_13.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_13)
self.label_17 = QtWidgets.QLabel(self.scrollAreaWidgetContents_13)
self.horizontalLayout_14.addWidget(self.label_17)
self.scrollArea_6.setWidget(self.scrollAreaWidgetContents_13)
self.horizontalLayout_16.addWidget(self.scrollArea_6)
self.scrollArea_5 = QtWidgets.QScrollArea(self.centralwidget)
self.scrollAreaWidgetContents_12 = QtWidgets.QWidget()
self.scrollAreaWidgetContents_12.setGeometry(QtCore.QRect(0, 0, 76, 200))
self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents_12)
self.label_18 = QtWidgets.QLabel(self.scrollAreaWidgetContents_12)
self.horizontalLayout_15.addWidget(self.label_18)
self.scrollArea_5.setWidget(self.scrollAreaWidgetContents_12)
self.horizontalLayout_16.addWidget(self.scrollArea_5)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
self.label_2.setText(_translate("MainWindow", "Окно 1"))
self.label_6.setText(_translate("MainWindow", "Окно 2"))
self.label_9.setText(_translate("MainWindow", "Окно 3"))
self.label_14.setText(_translate("MainWindow", "Окно 4"))
self.label_15.setText(_translate("MainWindow", "Окно 5"))
self.label_16.setText(_translate("MainWindow", "Окно 6"))
self.label_17.setText(_translate("MainWindow", "Окно 7"))
self.label_18.setText(_translate("MainWindow", "Окно 8"))
class ListWidget(QListWidget): # +++
def __init__(self, *args, **kwargs):
super(ListWidget, self).__init__(*args, **kwargs)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setEditTriggers(self.NoEditTriggers)
self.setFlow(self.LeftToRight)
self.setWrapping(True)
self.setResizeMode(self.Adjust)
self.setSpacing(10)
# Резиновая лента
self._rubberPos = None
self._rubberBand = QRubberBand(QRubberBand.Rectangle, self)
def makeItem(self, lb):
item = QtWidgets.QListWidgetItem(self)
item.setSizeHint(QtCore.QSize(170, 120)) # попробуйте другой size
self.setItemWidget(item, lb)
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__()
self.setupUi(self)
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
# Окно 1
self.scrollAreaWidgetContents_9.resize(200, 200)
# Окно 2
self.label_6.setAlignment(Qt.AlignCenter)
self.scrollAreaWidgetContents_8.resize(300, 300)
self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0)
_listWidget = [
self.scrollArea_2, self.scrollArea, self.scrollArea_3, self.scrollArea_4,
self.scrollArea_7, self.scrollArea_8, self.scrollArea_6, self.scrollArea_5,
]
self.listWidget = ListWidget()
box = QtWidgets.QVBoxLayout(self.centralwidget)
box.addWidget(self.listWidget)
for lbl in _listWidget:
self.listWidget.makeItem(lbl)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
app.setStyleSheet('QLabel {background-color: rgb(244,164,96);}')
w = Window()
w.resize(650, 450)
w.show()
sys.exit(app.exec_())
Такое можно сделать через FlowLayout, его нет в библиотеке, поэтому ниже реализация с примером.
Попробуйте:
from PyQt5.QtWidgets import QLayout, QSizePolicy
from PyQt5.QtCore import Qt, QRect, QSize, QPoint
# SOURCE: https://github.com/baoboa/pyqt5/blob/25bdb92c38d9c0a915c6366769cc00a63a1f04b2/examples/layouts/flowlayout.py#L65
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=0, spacing=-1):
super().__init__(parent)
if parent is not None:
self.setContentsMargins(margin, margin, margin, margin)
self.setSpacing(spacing)
self.itemList = []
def __del__(self):
item = self.takeAt(0)
while item:
item = self.takeAt(0)
def addItem(self, item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self, index):
if 0 <= index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self.doLayout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super().setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
margin, _, _, _ = self.getContentsMargins()
size += QSize(2 * margin, 2 * margin)
return size
def doLayout(self, rect, testOnly):
x = rect.x()
y = rect.y()
lineHeight = 0
for item in self.itemList:
wid = item.widget()
spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > rect.right() and lineHeight > 0:
x = rect.x()
y = y + lineHeight + spaceY
nextX = x + item.sizeHint().width() + spaceX
lineHeight = 0
if not testOnly:
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
x = nextX
lineHeight = max(lineHeight, item.sizeHint().height())
return y + lineHeight - rect.y()
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
class Window(QWidget):
def __init__(self):
super().__init__()
flowLayout = FlowLayout()
flowLayout.addWidget(QPushButton("Short"))
flowLayout.addWidget(QPushButton("Longer"))
flowLayout.addWidget(QPushButton("Different text"))
flowLayout.addWidget(QPushButton("More text"))
flowLayout.addWidget(QPushButton("Even longer button text"))
self.setLayout(flowLayout)
self.setWindowTitle("Flow Layout")
app = QApplication(sys.argv)
mw = Window()
mw.show()
sys.exit(app.exec_())




