Проблема с масштабированием виджетов в QScrollArea
Есть следующий минимально-воспроизводимый пример:
main.py:
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton
from PyQt5.uic import loadUi
class MyWindow(QDialog):
def __init__(self):
super().__init__()
loadUi('main.ui', self)
for i in range(15):
button = QPushButton(f'Button {i}')
self.verticalLayout.addWidget(button)
self.scrollArea.setWidgetResizable(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
main.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QScrollArea" name="scrollArea">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<height>301</height>
</rect>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>299</height>
</rect>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<height>301</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Необходимо, чтобы при заполнении QVBoxLayout
-а (verticalLayout
) кнопками (QPushButton
), они, кнопки, не масштабировались, а добавляли в QScrollArea
(scrollArea
) скроллинг. Т.е. как слева, а не как справа.
Нашел такой вариант:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QWidget, QScrollArea
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Пример QScrollArea без масштабирования виджетов')
self.setGeometry(100, 100, 300, 300)
# Создаем QScrollArea
self.scrollArea = QScrollArea(self)
self.scrollArea.setGeometry(10, 10, 280, 280)
# Создаем содержимое для QScrollArea
scroll_content_widget = QWidget()
scroll_content_layout = QVBoxLayout(scroll_content_widget)
# Добавляем кнопки в QVBoxLayout
for i in range(20):
button = QPushButton(f'Button {i}')
scroll_content_layout.addWidget(button)
# Устанавливаем содержимое для QScrollArea
self.scrollArea.setWidget(scroll_content_widget)
# Отключаем автоматическое масштабирование
self.scrollArea.setWidgetResizable(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
... он рабочий, но там логика не отделена от графического интерфейса, пытаюсь сделать из второго варианта первый, но где-то загвоздка и ничего не получается. main.ui делал в Qt Designer.
В чем проблема?
Ответы (1 шт):
У вас лишний менеджер компоновки и self.scrollArea.setWidgetResizable(True)
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton
#from PyQt5.uic import loadUi
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.scrollArea = QtWidgets.QScrollArea(Dialog)
self.scrollArea.setGeometry(QtCore.QRect(0, 0, 401, 301))
# !!!
self.scrollArea.setWidgetResizable(True) # !!!
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget() # !!!
self.scrollAreaWidgetContents.setEnabled(True)
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 399, 299))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
# self.verticalLayoutWidget = QtWidgets.QWidget(self.scrollAreaWidgetContents)
# self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 401, 301))
# self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
# self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
# ! +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents) # !!! +++
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.scrollArea.setWidget(self.scrollAreaWidgetContents) # !!!
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
class MyWindow(QDialog, Ui_Dialog):
def __init__(self):
super().__init__()
# loadUi('main.ui', self)
self.setupUi(self)
for i in range(15):
button = QPushButton(f'Button {i}')
button.clicked.connect(lambda ch, btn=button: print(f'Нажата {btn.text()}'))
self.verticalLayout.addWidget(button)
# ? self.scrollArea.setWidgetResizable(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Update:
я не совсем понимаю, что вы подразумеваете под лишним менеджером компоновки и self.scrollArea.setWidgetResizable(True).
Благодарю за работающий пример, но вопрос был в том, почему main.py не работает так, как надо и какие изменения в него (и/или main.ui) стоит внести, чтобы виджеты отображались нормально...хотелось, чтобы логика была отдельно, а интерфейс отдельно...
Я для вас сделал ровно то, что вы хотели и отметил в коде что не так.
То что ниже абсолютный аналог того что я написал выше.
main.py
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton
from PyQt5.uic import loadUi
class MyWindow(QDialog):
def __init__(self):
super().__init__()
loadUi('q1572176.ui', self)
for i in range(15):
button = QPushButton(f'Button {i}')
self.verticalLayout.addWidget(button)
# self.scrollArea.setWidgetResizable(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
q1572176.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QScrollArea" name="scrollArea">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<height>301</height>
</rect>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>299</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>