Python 如何将模型中的更改传播到视图?(使用pyqt信号和插槽)

Python 如何将模型中的更改传播到视图?(使用pyqt信号和插槽),python,pyqt4,signals-slots,Python,Pyqt4,Signals Slots,所以我有一个模型类,我想不知道它正在pyqt应用程序中运行。但同时,当模型发生变化时,我希望ui能够更新 我宁愿模型代码中没有pyqt信号。观测者模式感觉太多的代码只用于一件事情,那就是听它 这个问题的干净解决方案是什么 观测者模式感觉太多的代码只用于一件事情,那就是听它 实际上,观察者模式正是您所需要的,您根本不必使用PyQt信号/插槽。构建代码的正确方法是编写业务逻辑,而不知道GUI的存在,但是GUI应该对业务逻辑有弱引用 程序结构 我通常以如下方式启动PyQt应用程序: import sy

所以我有一个模型类,我想不知道它正在pyqt应用程序中运行。但同时,当模型发生变化时,我希望ui能够更新

我宁愿模型代码中没有pyqt信号。观测者模式感觉太多的代码只用于一件事情,那就是听它

这个问题的干净解决方案是什么

观测者模式感觉太多的代码只用于一件事情,那就是听它

实际上,观察者模式正是您所需要的,您根本不必使用PyQt信号/插槽。构建代码的正确方法是编写业务逻辑,而不知道GUI的存在,但是GUI应该对业务逻辑有弱引用

程序结构 我通常以如下方式启动PyQt应用程序:

import sys
import weakref
import PyQt4.QtGui as QtGui
from businesslogic import MyBusinessLogicClass
from guimodule import MyGuiClass    

app = QtGui.QApplication(sys.argv)
business_object = MyBusinessLogicClass()
gui = MyGuiClass(weakref.proxy(business_object))
sys.exit(app.exec_())
注意,gui通过弱引用接收对业务逻辑对象的引用。因此,当用户与gui交互时,gui可以向业务逻辑发送数据

从业务逻辑到gui获取信息 您的问题是关于业务逻辑如何将数据获取到gui,而不在其代码中显式引用gui。我已经通过制作一个装饰器解决了这个问题,我可以在我希望gui能够了解的函数和方法上添加装饰器。假设业务逻辑如下所示

# businesslogic.py
from observed import event  # Bear with me for a minute.

class MyBusinessLogicClass(object):
    @event
    def do_something_interesting(self, arg):
        print("logic back-end did something interesting with arg=%s"%(arg,))
这个小小的decorator@event使得其他东西可以注册,以便在调用dou\u有趣的东西时得到通知。gui就是这样做的

# guimodule.py

class MyGuiClass(QtGui.QMainWindow):
    def __init__(self, business):
        QtGui.QMainWindow.__init__(self)
        self.business = business
        business.do_something_interesting.addObserver(self.notify)
    
    def notify(self, arg):
        <present notification to the user>
请注意,MyBusinessLogicClass对gui一无所知。对代码的唯一入侵是@event decorator,它完全不知道GUI,事实上也完全不知道PyQt。还请注意,传递到MyBusinessLogicClass的arg被传递到GUI中的观察方法notify

观察者模式的实现 好的,这一切都很好,但它依赖于实现观察者模式的东西的存在来获得@event装饰器。您可以得到我的实现,称为“观察”,或者您可以直接执行

$pip安装已观察到

如果您在windows上,只需从github下载源发行版,然后在根目录中进行下载

>python setup.py安装

我真的希望这是有帮助的。我专门为这个用例开发了observed。它非常简单,但解决了我在python中看到的其他观察者模式实现的几个缺点

注意:我观察到的库正在开发中,所以自本文撰写以来,语法可能发生了一些变化

编辑:您说过您希望在不更改自定义类的情况下让所有这些都正常工作。虽然这是可能的,但我认为您必须在运行时弄乱方法的本质,这通常是不受欢迎的,因为它比直接在代码中执行操作更容易混淆和脆弱。如果将@event decorator添加到某些方法中过于麻烦,则可以将自定义类划分为子类,并在子类中添加decorator。您甚至可以使用自定义元类自动应用装饰器

观测者模式感觉太多的代码只用于一件事情,那就是听它

实际上,观察者模式正是您所需要的,您根本不必使用PyQt信号/插槽。构建代码的正确方法是编写业务逻辑,而不知道GUI的存在,但是GUI应该对业务逻辑有弱引用

程序结构 我通常以如下方式启动PyQt应用程序:

import sys
import weakref
import PyQt4.QtGui as QtGui
from businesslogic import MyBusinessLogicClass
from guimodule import MyGuiClass    

app = QtGui.QApplication(sys.argv)
business_object = MyBusinessLogicClass()
gui = MyGuiClass(weakref.proxy(business_object))
sys.exit(app.exec_())
注意,gui通过弱引用接收对业务逻辑对象的引用。因此,当用户与gui交互时,gui可以向业务逻辑发送数据

从业务逻辑到gui获取信息 您的问题是关于业务逻辑如何将数据获取到gui,而不在其代码中显式引用gui。我已经通过制作一个装饰器解决了这个问题,我可以在我希望gui能够了解的函数和方法上添加装饰器。假设业务逻辑如下所示

# businesslogic.py
from observed import event  # Bear with me for a minute.

class MyBusinessLogicClass(object):
    @event
    def do_something_interesting(self, arg):
        print("logic back-end did something interesting with arg=%s"%(arg,))
这个小小的decorator@event使得其他东西可以注册,以便在调用dou\u有趣的东西时得到通知。gui就是这样做的

# guimodule.py

class MyGuiClass(QtGui.QMainWindow):
    def __init__(self, business):
        QtGui.QMainWindow.__init__(self)
        self.business = business
        business.do_something_interesting.addObserver(self.notify)
    
    def notify(self, arg):
        <present notification to the user>
请注意,MyBusinessLogicClass对gui一无所知。对代码的唯一入侵是@event decorator,它完全不知道GUI,事实上也完全不知道PyQt。还请注意,传递到MyBusinessLogicClass的arg被传递到GUI中的观察方法notify

观察者模式的实现 好的,这一切都很好,但它依赖于实现观察者模式的东西的存在来获得@event装饰器。你可以得到我的实现,叫做 观察,或者你可以这样做

$pip安装已观察到

如果您在windows上,只需从github下载源发行版,然后在根目录中进行下载

>python setup.py安装

我真的希望这是有帮助的。我专门为这个用例开发了observed。它非常简单,但解决了我在python中看到的其他观察者模式实现的几个缺点

注意:我观察到的库正在开发中,所以自本文撰写以来,语法可能发生了一些变化


编辑:您说过您希望在不更改自定义类的情况下让所有这些都正常工作。虽然这是可能的,但我认为您必须在运行时弄乱方法的本质,这通常是不受欢迎的,因为它比直接在代码中执行操作更容易混淆和脆弱。如果将@event decorator添加到某些方法中过于麻烦,则可以将自定义类划分为子类,并在子类中添加decorator。您甚至可以使用自定义元类自动应用装饰程序。

我不太了解这种情况。这个模型是Qt模型还是一些数据?这是我自己的自定义类。我希望在不更改自定义类中的代码的情况下将其与pyqt集成。可以保持类的原样,但需要编写一个Qt模型,作为视图和类之间的通信器。View需要特定的API来访问数据,而Qt模型将为您的自定义类提供该接口。检查。如果其中一个令人满意,不要忘记接受答案。如果没有让你满意的答案,你可以随时发表评论要求澄清。我不太了解情况。这个模型是Qt模型还是一些数据?这是我自己的自定义类。我希望在不更改自定义类中的代码的情况下将其与pyqt集成。可以保持类的原样,但需要编写一个Qt模型,作为视图和类之间的通信器。View需要特定的API来访问数据,而Qt模型将为您的自定义类提供该接口。检查。如果其中一个令人满意,不要忘记接受答案。如果没有让你满意的答案,你可以随时发表评论要求澄清。