Inserindo uma guia em QTabWidget a partir de um layout predefinido

Dec 04 2020

Estou tentando adicionar guias ao meu QTabWidget dinamicamente e a coisa mais simples que quero fazer é duplicar a primeira guia predefinida que já tenho. Agora, antes de você me levar a esta pergunta: Botão para duplicar guias em um QTabWidget , ouça-me.

Não quero duplicar manualmente a guia. A guia que tenho é detalhada e pode ter grandes atualizações feitas a qualquer momento, eu gostaria de simplesmente editá-la no QTDesigner e talvez duplicá-la dinamicamente ou simplesmente inserir o formulário fornecido no QTabWidget. Eu tentei muitas coisas (ou seja: tentar fazer um formulário separado e importá-lo, projetar minha própria classe de página de guia [que funcionou, mas não é o que estou procurando], literalmente copiando o tabWidget e tentando adicioná-lo), mas nenhum deles parece fazer o truque.

Só preciso que uma guia seja inserida por meio de uma IU predefinida.

EDITAR:

Depois de criar um formulário por meio do software QtDesigner e exportá-lo para um arquivo python, recebo este código:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'newTab.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(810, 672)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.testIdFrame = QtWidgets.QFrame(Form)
        self.testIdFrame.setMinimumSize(QtCore.QSize(0, 622))
        font = QtGui.QFont()
        font.setFamily("Segoe UI Black")
        font.setBold(True)
        font.setItalic(True)
        font.setUnderline(False)
        font.setWeight(75)
        self.testIdFrame.setFont(font)
        self.testIdFrame.setStyleSheet("background: transparent;")
        self.testIdFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.testIdFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.testIdFrame.setObjectName("testIdFrame")
        self.atpDropBox = QtWidgets.QComboBox(self.testIdFrame)
        self.atpDropBox.setGeometry(QtCore.QRect(120, 20, 98, 31))
        self.atpDropBox.setObjectName("atpDropBox")
        self.snLabel = QtWidgets.QLabel(self.testIdFrame)
        self.snLabel.setGeometry(QtCore.QRect(260, 30, 32, 21))
        self.snLabel.setObjectName("snLabel")
        self.workOrderLabel = QtWidgets.QLabel(self.testIdFrame)
        self.workOrderLabel.setGeometry(QtCore.QRect(10, 30, 75, 21))
        self.workOrderLabel.setObjectName("workOrderLabel")
        self.powerSupplyLabel1 = QtWidgets.QLabel(self.testIdFrame)
        self.powerSupplyLabel1.setGeometry(QtCore.QRect(10, 70, 101, 21))
        self.powerSupplyLabel1.setObjectName("powerSupplyLabel1")
        self.snTextEdit = QtWidgets.QTextEdit(self.testIdFrame)
        self.snTextEdit.setGeometry(QtCore.QRect(300, 20, 131, 31))
        self.snTextEdit.setStyleSheet("QTextEdit {\n"
"border: 1px solid black;\n"
"border-radius:5px; \n"
"}")
        self.snTextEdit.setObjectName("snTextEdit")
        self.voltageTextEdit1 = QtWidgets.QTextEdit(self.testIdFrame)
        self.voltageTextEdit1.setGeometry(QtCore.QRect(200, 60, 101, 31))
        self.voltageTextEdit1.setAutoFillBackground(False)
        self.voltageTextEdit1.setStyleSheet("QTextEdit {\n"
"border: 1px solid black;\n"
"border-radius:5px; \n"
"}")
        self.voltageTextEdit1.setObjectName("voltageTextEdit1")
        self.voltageLabel1 = QtWidgets.QLabel(self.testIdFrame)
        self.voltageLabel1.setGeometry(QtCore.QRect(120, 70, 71, 21))
        self.voltageLabel1.setObjectName("voltageLabel1")
        self.voltageLabel2 = QtWidgets.QLabel(self.testIdFrame)
        self.voltageLabel2.setGeometry(QtCore.QRect(120, 110, 71, 21))
        self.voltageLabel2.setObjectName("voltageLabel2")
        self.voltageTextEdit2 = QtWidgets.QTextEdit(self.testIdFrame)
        self.voltageTextEdit2.setGeometry(QtCore.QRect(200, 100, 101, 31))
        self.voltageTextEdit2.setAutoFillBackground(False)
        self.voltageTextEdit2.setStyleSheet("QTextEdit {\n"
"border: 1px solid black;\n"
"border-radius:5px; \n"
"}")
        self.voltageTextEdit2.setObjectName("voltageTextEdit2")
        self.powerSupplyLabel2 = QtWidgets.QLabel(self.testIdFrame)
        self.powerSupplyLabel2.setGeometry(QtCore.QRect(10, 110, 101, 21))
        self.powerSupplyLabel2.setObjectName("powerSupplyLabel2")
        self.currentLabel2 = QtWidgets.QLabel(self.testIdFrame)
        self.currentLabel2.setGeometry(QtCore.QRect(310, 110, 81, 21))
        self.currentLabel2.setObjectName("currentLabel2")
        self.currentLabel1 = QtWidgets.QLabel(self.testIdFrame)
        self.currentLabel1.setGeometry(QtCore.QRect(310, 70, 91, 21))
        self.currentLabel1.setObjectName("currentLabel1")
        self.currentTextEdit1 = QtWidgets.QTextEdit(self.testIdFrame)
        self.currentTextEdit1.setGeometry(QtCore.QRect(400, 60, 101, 31))
        self.currentTextEdit1.setAutoFillBackground(False)
        self.currentTextEdit1.setStyleSheet("QTextEdit {\n"
"border: 1px solid black;\n"
"border-radius:5px; \n"
"}")
        self.currentTextEdit1.setObjectName("currentTextEdit1")
        self.currentTextEdit2 = QtWidgets.QTextEdit(self.testIdFrame)
        self.currentTextEdit2.setGeometry(QtCore.QRect(400, 100, 101, 31))
        self.currentTextEdit2.setAutoFillBackground(False)
        self.currentTextEdit2.setStyleSheet("QTextEdit {\n"
"border: 1px solid black;\n"
"border-radius:5px; \n"
"}")
        self.currentTextEdit2.setObjectName("currentTextEdit2")
        self.verticalLayout.addWidget(self.testIdFrame)
        self.RXFrame = QtWidgets.QFrame(Form)
        self.RXFrame.setStyleSheet("background: transparent;")
        self.RXFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.RXFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.RXFrame.setObjectName("RXFrame")
        self.verticalLayout.addWidget(self.RXFrame)
        self.TXFrame = QtWidgets.QFrame(Form)
        self.TXFrame.setStyleSheet("background: transparent;")
        self.TXFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.TXFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.TXFrame.setObjectName("TXFrame")
        self.verticalLayout.addWidget(self.TXFrame)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.snLabel.setText(_translate("Form", "SN:"))
        self.workOrderLabel.setText(_translate("Form", "Work Order:"))
        self.powerSupplyLabel1.setText(_translate("Form", "Power Supply 1:"))
        self.voltageLabel1.setText(_translate("Form", "Voltage [V]:"))
        self.voltageLabel2.setText(_translate("Form", "Voltage [V]:"))
        self.powerSupplyLabel2.setText(_translate("Form", "Power Supply 2:"))
        self.currentLabel2.setText(_translate("Form", "Current [mA]:"))
        self.currentLabel1.setText(_translate("Form", "Current [mA]:"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

Na minha classe MainWindow, eu importo o Ui_Form do arquivo python recém-gerado que contém o conteúdo da nova guia que gostaria de duplicar. É aqui que fico preso. Chamo a função que criará minhas guias para mim:

def buildTabs(self, numberOfTabs): 
    for dut in range(numberOfTabs): 
        text = ('TAB ' + ascii_uppercase[dut]) 
        self.ui.tabWidget.addTab(Ui_Form(), text)

O widget da guia está na interface do usuário da janela principal.

Eu não entendo como posso transformar o Ui_Form () em um Ui_TabPage ou um QWidget como mostrado nesta pergunta

Formulário QT Designer:

insira a descrição da imagem aqui

Respostas

musicamante Dec 04 2020 at 02:57

Os arquivos gerados por pyuic são classes de formulário , na verdade são objectclasses python padrão e precisam de uma instância QWidget (ou qualquer classe usada no Designer para essa interface do usuário, como um QDialog) para "construí-los".

def buildTabs(self, numberOfTabs): 
    for dut in range(numberOfTabs): 
        page = QtWidgets.QWidget()
        page.ui = Ui_Form()
        page.ui.setupUi(page)        
        text = ('TAB ' + ascii_uppercase[dut])
        self.ui.tabWidget.addTab(page, text)

Considere que PyQt e PySide não podem ser misturados, portanto, se você estiver usando PyQt, o comando sim pyuic, enquanto com PySide o comando sim pyside2-uic.

Observe que se você precisar de mais interação com as páginas de guia , geralmente é melhor subclassificá-las:

class PageOne(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

        self.ui.someButton.clicked.connect(self.someFunction)
        # ...

Ou melhor, com o método de herança múltipla, que evita acessar constantemente os elementos da interface do usuário por meio do ui"subobjeto":

class PageOne(QtWidgets.QWidget, Ui_Form):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

        self.someButton.clicked.connect(self.someFunction)
        # ...

E depois:

def buildTabs(self, numberOfTabs): 
    for dut in range(numberOfTabs): 
        page = PageOne()
        text = ('TAB ' + ascii_uppercase[dut])
        self.ui.tabWidget.addTab(page, text)