python - wx.lib.pubsub.Publisher在按钮点击时无法工作?

1 投票
1 回答
1628 浏览
提问于 2025-04-16 07:26

我正在用 MVC 模式开发一个应用程序,使用的是 wxPython,但遇到了一个关于 wx.lib.pubsub.Publisher 的问题。

我希望我的控制器和视图尽量分开。比如说,我不想让控制器知道视图中按钮的名字。在 wxPython 的示例 中,控制器必须知道这些名字,这样才能把动作绑定到这些按钮上。

class Controller:
...
self.view2.add.Bind(wx.EVT_BUTTON, self.AddMoney)
self.view2.remove.Bind(wx.EVT_BUTTON, self.RemoveMoney)

我想过要“解耦”一下,改用 wx.lib.pubsub.Publisher 的消息来处理:

from wx.lib.pubsub import Publisher as pub

class Controller:
...
pub.subscribe(self.AddMoney, "MONEY ADDED")
pub.subscribe(self.RemoveMoney, "MONEY REMOVED")

视图会把控件绑定到一个动作,这个动作只是发送消息。

但是,结果似乎不太对。要么视图不发送事件,要么控制器不接收来自视图的消息。我也不太确定。

这里有一个小示例应用,展示了我的问题(我在 python 2.6.6 和 wxPython 2.8 上测试过)。

import wxversion
wxversion.ensureMinimal('2.8')
import wx
from wx.lib.pubsub import Publisher as pub

class View(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Main View")

        self.button = wx.Button(self, -1, "foo?")
        self.button.Bind(wx.EVT_BUTTON, self.ChangeFoo)

    def ChangeFoo(self, evt):
        print('Binding works')
        pub.sendMessage("FOO CHANGED")

class Controller:
    def __init__(self, app):
        self.view = View()

        pub.subscribe(self.FooChanged, "FOO CHANGED")

        self.view.Show()

    def FooChanged(self, message):
        print('Messaging works')


app = wx.App(False)
Controller(app)
app.MainLoop()

这个应用会显示一个窗口,里面有一个大按钮。按下这个按钮后,预期的输出是:

Binding works
Messaging works

但实际上我得到的是:

Binding works

有没有人知道怎么解决这个问题?

1 个回答

4

你需要保存一个对控制器的引用,否则这个对象会被垃圾回收(GC),到发送消息时就不存在了。把倒数第二行改成:

controller = Controller(app)

撰写回答