PyQt6, Qt Designer. Как настакать отдельный фрейм на мейн_виндов в скролл_ареа?

Создал в Qt Designer мейн_виндов, в котором располагается QScrollArea.

Также имеется отдельный виджет, который в свою очередь должен располагаться внутри QScrollArea.

В интернете уйма решений, так или иначе все они работают, если я сильно упрощаю свой код. Но вот с тем кодом, который мне необходим, завести не получается.

Вот паста главного окна: main_window.py

Вот тут код виджета: frame.py

Вот таким образом выглядит код, который, собственно, и запускает всю карусель:

from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QMainWindow
from main_window import Ui_MainWindow
from frame import Ui_Form

import sys


class MainWindow:
    def __init__(self):
        self.window = QMainWindow()
        self.main_ui = Ui_MainWindow()
        self.main_ui.setupUi(self.window)
        self.form_ui = Ui_Form()

        self.scroll = self.main_ui.scrollArea
        self.widget = self.main_ui.scrollAreaContents
        self.vbox = self.main_ui.verticalLayout_2

        self.stack_frames()

        self.form_ui.btn_about_file.clicked.connect(self.show_about_file)
        self.main_ui.btn_back.clicked.connect(self.show_main_page)

    def stack_frames(self):
        for i in range(50):
            object = self.form_ui.setupUi(self.widget)
            self.vbox.addWidget(object)
        self.scroll.setWidget(self.widget)

    def show_about_file(self):
        self.main_ui.main_stackedWidget.setCurrentWidget(self.main_ui.about_page)

    def show_main_page(self):
        self.main_ui.main_stackedWidget.setCurrentWidget(self.main_ui.main_page)

    def show(self):
        self.window.show()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

Вся магия происходит в функции stack_frames.

Вот так выглядит один виджет в главном окне:

А вот так, если виджетов несколько:

Все элементы виджета улетают в верхний левый угол.

Помогите разобрать этот момент. Спасибо.


Ответы (1 шт):

Автор решения: S. Nick

Я отметил для вас строки, в которые надо внести изменения. Если что-то будет не понятно - спросите.

#from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtGui, QtWidgets 
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow

#from main_window import Ui_MainWindow
#from frame import Ui_Form
 
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(940, 50)
        Form.setMinimumSize(QtCore.QSize(0, 50))
        Form.setMaximumSize(QtCore.QSize(16777215, 50))
        self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.btn_about_file = QtWidgets.QPushButton(Form)
        self.btn_about_file.setMinimumSize(QtCore.QSize(0, 30))
        self.btn_about_file.setSizeIncrement(QtCore.QSize(0, 0))
        self.btn_about_file.setBaseSize(QtCore.QSize(0, 0))
        self.btn_about_file.setObjectName("btn_about_file")
        self.horizontalLayout.addWidget(self.btn_about_file)
        self.line_3 = QtWidgets.QFrame(Form)
        self.line_3.setFrameShape(QtWidgets.QFrame.Shape.VLine)
        self.line_3.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
        self.line_3.setObjectName("line_3")
        self.horizontalLayout.addWidget(self.line_3)
        self.label_file_name = QtWidgets.QLabel(Form)
        self.label_file_name.setObjectName("label_file_name")
        self.horizontalLayout.addWidget(self.label_file_name)
        spacerItem = QtWidgets.QSpacerItem(1000, 20, 
            QtWidgets.QSizePolicy.Policy.Expanding, 
            QtWidgets.QSizePolicy.Policy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.line_1 = QtWidgets.QFrame(Form)
        self.line_1.setFrameShape(QtWidgets.QFrame.Shape.VLine)
        self.line_1.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
        self.line_1.setObjectName("line_1")
        self.horizontalLayout.addWidget(self.line_1)
        self.label_data = QtWidgets.QLabel(Form)
        self.label_data.setMinimumSize(QtCore.QSize(150, 0))
        self.label_data.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
        self.label_data.setObjectName("label_data")
        self.horizontalLayout.addWidget(self.label_data)
        self.line_2 = QtWidgets.QFrame(Form)
        self.line_2.setFrameShape(QtWidgets.QFrame.Shape.VLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
        self.line_2.setObjectName("line_2")
        self.horizontalLayout.addWidget(self.line_2)
        self.label_creator = QtWidgets.QLabel(Form)
        self.label_creator.setMinimumSize(QtCore.QSize(150, 0))
        self.label_creator.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
        self.label_creator.setObjectName("label_creator")
        self.horizontalLayout.addWidget(self.label_creator)
        self.line = QtWidgets.QFrame(Form)
        self.line.setFrameShape(QtWidgets.QFrame.Shape.VLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
        self.line.setObjectName("line")
        self.horizontalLayout.addWidget(self.line)
        self.btn_process = QtWidgets.QPushButton(Form)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Policy.Expanding, 
            QtWidgets.QSizePolicy.Policy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.btn_process.sizePolicy().hasHeightForWidth())
        self.btn_process.setSizePolicy(sizePolicy)
        self.btn_process.setMinimumSize(QtCore.QSize(0, 30))
        self.btn_process.setSizeIncrement(QtCore.QSize(100, 0))
        self.btn_process.setBaseSize(QtCore.QSize(0, 0))
        self.btn_process.setObjectName("btn_process")
        self.horizontalLayout.addWidget(self.btn_process)
        self.btn_ready = QtWidgets.QPushButton(Form)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Policy.Expanding, 
            QtWidgets.QSizePolicy.Policy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.btn_ready.sizePolicy().hasHeightForWidth())
        self.btn_ready.setSizePolicy(sizePolicy)
        self.btn_ready.setMinimumSize(QtCore.QSize(0, 30))
        self.btn_ready.setSizeIncrement(QtCore.QSize(100, 0))
        self.btn_ready.setBaseSize(QtCore.QSize(0, 0))
        self.btn_ready.setObjectName("btn_ready")
        self.horizontalLayout.addWidget(self.btn_ready)
 
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
 
    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.btn_about_file.setText(_translate("Form", ">>>"))
        self.label_file_name.setText(_translate("Form", "File name"))
        self.label_data.setText(_translate("Form", "Data | Time"))
        self.label_creator.setText(_translate("Form", "Creator"))
        self.btn_process.setText(_translate("Form", "Process"))
        self.btn_ready.setText(_translate("Form", "Ready"))
 
 
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 668)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, 
            QtWidgets.QSizePolicy.Policy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(1000, 600))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        
        self.main_stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
        self.main_stackedWidget.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
        self.main_stackedWidget.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
        self.main_stackedWidget.setObjectName("main_stackedWidget")
        
        self.main_stackedWidget.setStyleSheet("background-color: #aaf;")  # +
        
        self.main_page = QtWidgets.QWidget()
        self.main_page.setObjectName("main_page")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.main_page)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.scrollArea = QtWidgets.QScrollArea(self.main_page)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        
        self.scrollArea.setStyleSheet("background-color: #aaa;")          # +
        
        self.scrollAreaContents = QtWidgets.QWidget()
        self.scrollAreaContents.setGeometry(QtCore.QRect(0, 0, 960, 600))
        self.scrollAreaContents.setObjectName("scrollAreaContents")
        self.scrollArea.setWidget(self.scrollAreaContents)

        self.verticalLayout_2.addWidget(self.scrollArea)
        
        self.main_stackedWidget.addWidget(self.main_page)
        self.about_page = QtWidgets.QWidget()
        self.about_page.setObjectName("about_page")
        
        self.about_page.setStyleSheet("background-color: #afa;")          # +
        
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.about_page)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        
        self.btn_back = QtWidgets.QPushButton(self.about_page)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_back.sizePolicy().hasHeightForWidth())
        self.btn_back.setSizePolicy(sizePolicy)
        self.btn_back.setMaximumSize(QtCore.QSize(40, 16777215))
        self.btn_back.setObjectName("btn_back")
        self.horizontalLayout_2.addWidget(self.btn_back)
        
        self.frame_about = QtWidgets.QFrame(self.about_page)
        self.frame_about.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
        self.frame_about.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
        self.frame_about.setObjectName("frame_about")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.frame_about)
        self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_3.setSpacing(6)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.text_about = QtWidgets.QPlainTextEdit(self.frame_about)
        self.text_about.setReadOnly(True)
        self.text_about.setObjectName("text_about")
        self.verticalLayout_3.addWidget(self.text_about)
        self.horizontalLayout_2.addWidget(self.frame_about)
        self.frame_chat = QtWidgets.QFrame(self.about_page)
        self.frame_chat.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
        self.frame_chat.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
        self.frame_chat.setObjectName("frame_chat")
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.frame_chat)
        self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.text_chat = QtWidgets.QPlainTextEdit(self.frame_chat)
        self.text_chat.setReadOnly(True)
        self.text_chat.setObjectName("text_chat")
        self.verticalLayout_4.addWidget(self.text_chat)
        self.widgetSendMessage = QtWidgets.QWidget(self.frame_chat)
        self.widgetSendMessage.setObjectName("widgetSendMessage")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widgetSendMessage)
        self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.line_write_message = QtWidgets.QLineEdit(self.widgetSendMessage)
        self.line_write_message.setMinimumSize(QtCore.QSize(0, 40))
        self.line_write_message.setObjectName("line_write_message")
        self.horizontalLayout_3.addWidget(self.line_write_message)
        self.btn_send = QtWidgets.QPushButton(self.widgetSendMessage)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_send.sizePolicy().hasHeightForWidth())
        self.btn_send.setSizePolicy(sizePolicy)
        self.btn_send.setMinimumSize(QtCore.QSize(0, 40))
        self.btn_send.setObjectName("btn_send")
        self.horizontalLayout_3.addWidget(self.btn_send)
        self.btn_alarm = QtWidgets.QPushButton(self.widgetSendMessage)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_alarm.sizePolicy().hasHeightForWidth())
        self.btn_alarm.setSizePolicy(sizePolicy)
        self.btn_alarm.setMinimumSize(QtCore.QSize(0, 40))
        self.btn_alarm.setMaximumSize(QtCore.QSize(16777215, 40))
        self.btn_alarm.setObjectName("btn_alarm")
        self.horizontalLayout_3.addWidget(self.btn_alarm)
        self.verticalLayout_4.addWidget(self.widgetSendMessage)
        self.horizontalLayout_2.addWidget(self.frame_chat)
        
        self.main_stackedWidget.addWidget(self.about_page)
        
        self.horizontalLayout.addWidget(self.main_stackedWidget)
        
        MainWindow.setCentralWidget(self.centralwidget)
 
        self.retranslateUi(MainWindow)
        self.main_stackedWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
 
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "PCRM"))
        self.btn_back.setText(_translate("MainWindow", "<"))
        self.text_about.setPlainText(_translate("MainWindow", "About File!"))
        self.btn_send.setText(_translate("MainWindow", "Send"))
        self.btn_alarm.setText(_translate("MainWindow", "Alarm!"))

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class Form(QtWidgets.QWidget, Ui_Form):                                # +++
    def __init__(self):
        super().__init__()     
        self.setupUi(self)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):         # +++  Ui_MainWindow
    def __init__(self):
        super().__init__()                                      # +++
    
#        self.window = QMainWindow()
#        self.main_ui = Ui_MainWindow()
#        self.main_ui.setupUi(self.window)
        self.setupUi(self)                                      # +++
        
#        self.form_ui = Ui_Form()
#        self.scroll = self.main_ui.scrollArea
#        self.widget = self.main_ui.scrollAreaContents
#        self.vbox = self.main_ui.verticalLayout_2

#                                              vvvvvvvvvvvvvvvvvv      <---- 
        self.vbox = QtWidgets.QVBoxLayout(self.scrollAreaContents)     # +++

        self.stack_frames()

# ?        self.form_ui.btn_about_file.clicked.connect(self.show_about_file)
        self.btn_back.clicked.connect(self.show_main_page)

#    def stack_frames(self):
#        for i in range(50):
#            object = self.form_ui.setupUi(self.widget)
#            self.vbox.addWidget(object)
#        self.scroll.setWidget(self.widget)

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    def stack_frames(self):
        for i in range(50):
            form = Form()                                               # !!!
            form.btn_about_file.clicked.connect(self.show_about_file)   # !!!
            self.vbox.addWidget(form)                                   # !!!
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    def show_about_file(self):
        self.main_stackedWidget.setCurrentWidget(self.about_page)

    def show_main_page(self):
        self.main_stackedWidget.setCurrentWidget(self.main_page)

# ?    def show(self):
#        self.window.show()


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())    

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка