如何使用 pyside2 插槽函数共享数据?

Posted

技术标签:

【中文标题】如何使用 pyside2 插槽函数共享数据?【英文标题】:How can I share data with a pyside2 slot function? 【发布时间】:2019-08-23 14:05:36 【问题描述】:

我有一个PySide2 GUI 应用程序,它带有一个QPushButton 按钮和一个连接到它的@Slot 函数。如何与函数共享数据?

from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout

@Slot()
def button_XYZ_callback():
    # Function which is executed when the button XYZ is clicked.
    # I'd like to access the __main__s context data "parent_data" here.
    pass

if __name__ == '__main__':
    # parent context data what I want to access (read only)
    parent_data = "blub"

    application = QApplication(sys.argv)
    window = QMainWindow()
    central_widget = QWidget()
    xyz_button = QPushButton("XYZ", central_widget)
    xyz_button.clicked.connect(button_xyz_callback)
    layout = QVBoxLayout(central_widget)
    layout.addWidget(xyz_button)
    window.show()
    sys.exit(application.exec_())

【问题讨论】:

你能发一个minimal example你想要达到的目标吗? 根据 Python 的 LEGB rule,可以从 button_XYZ_callback 函数中访问全局变量 parent_data @unutbu 我知道,但全局变量通常被认为是糟糕的设计。我想知道这是否是我还不知道的其他 pyside 特定机制。 【参考方案1】:

根据Python's LEGB rule,可以从button_XYZ_callback 函数中访问全局变量parent_data

但是,如果您希望减少函数对全局变量的依赖,标准技术是定义一个类,并使用类或实例属性来存储全局值之前的内容:

# based on code from https://wiki.qt.io/Qt_for_Python_Tutorial_ClickableButton
import sys
from PySide2 import QtCore, QtWidgets, QtGui


class MyWidget(QtWidgets.QWidget):
    def __init__(self, data):

        QtWidgets.QWidget.__init__(self)
        self.data = data
        self.button = QtWidgets.QPushButton("Click me!")
        self.text = QtWidgets.QLabel("Hello World")
        self.text.setAlignment(QtCore.Qt.AlignCenter)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)
        self.button.clicked.connect(self.button_XYZ_callback)

    @QtCore.Slot()
    def button_XYZ_callback(self):
        print(self.data)

if __name__ == "__main__":
    parent_data = "blub"
    app = QtWidgets.QApplication(sys.argv)
    widget = MyWidget(data=parent_data)
    widget.show()
    sys.exit(app.exec_())

或者,如果在定义回调之前数据是已知的,则可以使用函数工厂将数据放在回调的封闭范围内:

import sys
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QPushButton


def make_callback(data):
    @Slot()
    def button_XYZ_callback():
        print(data)
    return button_XYZ_callback

if __name__ == "__main__":
    parent_data = "blub"
    # https://wiki.qt.io/Qt_for_Python_Tutorial_ClickableButton
    app = QApplication(sys.argv)
    button = QPushButton("Click me")
    button.clicked.connect(make_callback(parent_data))
    button.show()
    app.exec_()

【讨论】:

class MyWidget(QtWidgets.QWidget)之外定义class MyWindow(QMainWindow)并在构建时将窗口实例传递给widget是否合理? 小部件应该为小部件可以做的所有事情定义方法,但不需要知道关于窗口更大世界的任何事情。 Window 应该知道它包含的小部件并定义它们如何交互。以这种方式组织,一个 Widget 可以被多个窗口或应用程序以可能不同的方式使用。 这种职责分离有助于保持代码的组织性、可维护性、可扩展性和可重用性。因此,more usual 在 Window 的 __init__ 内创建 Widget 实例,而不是将窗口实例传递给 Widget 的 __init__ 我已经在 Window 的 __init__ 中创建了 Widget 实例。只是想知道是否还有其他模式。谢谢。

以上是关于如何使用 pyside2 插槽函数共享数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何将信号连接到 2 个共享库之间的插槽

使用 Qt Designer 在 PySide2 中实现信号/插槽时出错

将 QML 信号连接到 PySide2 插槽

是否可以通过 QML 从 PySide2 插槽(服务调用)获取对象列表?

如何从共享库的文本部分获取偏移量和数据?

进程通信之内存共享篇