Как создавать новые виджеты через функцию в PyQt?

Необходимо чтобы создавался новый элемент по нажатию кнопки, например, новая кнопка.

Могут ли создаваться новые элементы вне основной функции setupUI?

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.resize(600, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)

        self.but = QtWidgets.QPushButton(self.centralwidget)
        self.but.setGeometry(QtCore.QRect(100,100,100,100))
        self.but.setStyleSheet('background-color:blue')
        self.but.clicked.connect(self.click)

        MainWindow.setCentralWidget(self.centralwidget)

    def click(self):
        self.but2 = QtWidgets.QPushButton(self.centralwidget)
        self.but2.setGeometry(QtCore.QRect(200,200,100,100))
        self.but2.setStyleSheet('background-color:red')

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

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

Автор решения: eri

Наверное Вы забыли вызвать метод show()

self.but2.show()
→ Ссылка
Автор решения: S. Nick

Да, если вы не и используете менеджеры компоновки и вы создаете новый виджет, то вам надо показывает этот новый виджет.

Абсолютное позиционирование - это плохая практика.
Советую вам ознакомиться с Layout Management - cистема компоновки Qt предоставляет простой и мощный способ автоматического размещения дочерних виджетов внутри виджета, чтобы убедиться, что они эффективно используют доступное пространство...

НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный Qt Designer, НИКОГДА.
Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.

А теперь почувствуйте разницу:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.resize(600, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)

        self.but = QtWidgets.QPushButton(self.centralwidget)
        self.but.setFixedSize(QtCore.QSize(100, 100))
        self.but.setStyleSheet('background-color:blue')

        MainWindow.setCentralWidget(self.centralwidget)
 

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        
        main_layout = QtWidgets.QVBoxLayout(self.centralwidget)
        scrollArea  = QtWidgets.QScrollArea() 
        main_layout.addWidget(scrollArea)
        self.widget = QtWidgets.QWidget() 
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setSpacing(0)
        scrollArea.setWidget(self.widget)
        scrollArea.setWidgetResizable(True)         
        
        self.row = 1
        self.column = 1
        self.gridLayout.addWidget(self.but, self.row, self.column)
        
        self.but.clicked.connect(self.clicked_but)

    def clicked_but(self):
        self.row += 1
        self.column += 1        
        new_but = QtWidgets.QPushButton(self.centralwidget)
        new_but.setFixedSize(QtCore.QSize(100, 100))
        new_but.setStyleSheet('background-color:red')
        self.gridLayout.addWidget(new_but, self.row, self.column)
 

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

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

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

→ Ссылка