如何在 PyQt5 / PySide2 中从一个类访问属性到另一个类

Posted

技术标签:

【中文标题】如何在 PyQt5 / PySide2 中从一个类访问属性到另一个类【英文标题】:How to access attribut from one class to another class in PyQt5 / PySide2 【发布时间】:2021-04-20 15:25:48 【问题描述】:

我无法访问 Ui_MainWindow 类中的属性 self.horizo​​ntalLayout_Base,我想在其中添加新的小部件。

有:

    继承类Ui_MainWindow的主类MainWindowUi_MainWindow 类创建布局。 类对话提供额外信息和确认或取消。

主类 MainWindow 调用类 Dialog。查询Dialog类,然后调用MainWindow类中的tableWidget方法。但是无法访问由 Ui_MainWindow 类创建的属性 self.horizo​​ntalLayout_Base

有什么方法可以访问吗?

主类MainWindow

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        
        ...
        
        self.setupUi(self)
        
        ...
        
        
    def tableWidget(self):
        if len(list) > 0:
            row = len(list)
            clmn = len(list[0]) 
            self.tableWidget = QTableWidget(row, clmn + 1)
        else:
            return
        self.vbox = QVBoxLayout()

        ...

        Ui_MainWindow.gridLayout_Base.addLayout(self.vbox) # Here I want to get access

布局类 Ui_MainWindow

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1110, 772)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
        self.centralwidget.setSizePolicy(sizePolicy)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")

        self.horizontalLayout_Base = QtWidgets.QHBoxLayout() # This is target

        ...

类对话框

class Dialog(QDialog):

    NumGridRows = 3
    NumButtons = 4

    def __init__(self, souradnice):
        super(Dialog, self).__init__()
        ...

    def buttonAccepted(self):
        ...

        MainWindow.tableWidget(self)
        self.close()

【问题讨论】:

如果你想添加一个QTableWidget,那你为什么要创建一个布局? 这是一个基于事件的附加小部件 对不起,您的回答没有多大意义。小部件和布局是两个完全不同的东西。 其他小部件是使用布局中的 QTableWidget 创建的,我需要将 vbox 布局中的这个“包”放入 Ui_MainWindow.gridLayout_Base.addLayout(self.vbox)。 供将来参考,如果您只想共享部分代码,那可能没问题,但前提是其余部分有意义。提供一个最小的 [可重现] 示例并不意味着尽可能少地共享代码,因为我们无法知道您遗漏的所有内容,这可能会使阅读您的代码感到困惑。 “最少”意味着您应该向我们提供任何人阅读和理解您的代码的作用所需的最少代码。 【参考方案1】:

您似乎对什么是类、实例及其方法感到困惑(为此,我强烈建议您进行一些研究,因为它们是 OOP 的基本方面,不容忽视)。

tableWidget 中,您无法从Ui_MainWindow 访问gridLayout_Base,因为这是一个类。由于您都继承自 QMainWindow Ui_MainWindow,并且您正在调用setupUi(self),这意味着 ui 的所有属性实际上都是作为 instance 的属性成员创建的,因此您只需使用 self.gridLayout_Base 即可访问布局。 然后,如果要添加布局,则必须使用 addLayout(),而不是 addWidget()(仅适用于小部件)。

    def tableWidget(self):
        # ...
        self.gridLayout_Base.addLayout(self.vbox)

那么,我不知道你是如何创建和打开对话框的,但你当然不能调用MainWindow.tableWidget(self):这将导致调用该方法并以 dialog 实例作为第一个参数(self),因此您不会向主窗口添加任何内容。

一种更好更安全的方法(这也是普遍接受的做法)是通过调用其exec() 将对话框显示为模态,然后根据结果对其作出反应。为了正确实现这一点,您不应在对话框上调用self.close()(这会导致拒绝它),而应调用self.accept()

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    # ...
    def someFunctionToShowDialog(self):
        dialog = Dialog(self)
        if dialog.exec_():
            parameters = dialog.getValues()
            self.tableWidget()
            self.doSomethingWithParameters(parameters)


class Dialog(QDialog):
    # ...
    def buttonAccepted(self):
        self.accept()

    def getValues(self):
        return self.someValue, self.anotherValue

【讨论】:

感谢您的建议。当我做dialog = Dialog(self) 对话框时,打开另一个对话框。当我写self.gridLayout_Base.addLayout(self.vbox) 然后: AttributeError: 'Dialog' object has no attribute 'gridLayout_Base' 我尝试显示代码.. @Pr.Syn 如前所述,我不知道您是如何创建对话框的,因此请阅读我的代码并尝试了解它的作用。关于第二个错误,这意味着您正在尝试从对话框中调用tableWidget (这没有意义),或者您做错了其他事情。 谢谢,我明白了......我被卡住了,我没有看到这种可能性,但多亏了你,我找到了解决方案。

以上是关于如何在 PyQt5 / PySide2 中从一个类访问属性到另一个类的主要内容,如果未能解决你的问题,请参考以下文章

如何断开 PySide2 中的按钮单击信号?

在 PyQt5 和 PySide2 中覆盖paintEvent

在 PyQt5/Pyside2 中动态添加小部件到流布局

了解不一致的 cythonized 代码行为 - PyQt5 与 PySide2

PyQt5 & PySide2 / 无法在“”中加载 Qt 平台插件“windows”,即使找到了

PySide2 与 Pyqt5 的区别