7.1 KiB
wxPython 和 PubSub:一个简单的教程
原文:https://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
我在 wxPython 邮件列表或其 IRC 频道上看到许多关于框架间通信的问题,大多数时候开发人员需要的是 PubSub 模块。发布者/订阅者模型是向一个或多个侦听器发送消息的一种方式。你可以在这里阅读。据说观察者模式是基于发布/订阅模式的。在 wxPython land 中,我们有 pubsub 模块,可以从 wx.lib.pubsub 中访问。它实际上包含在 wxPython 中,但你也可以从其源 Forge 中下载它作为一个独立的模块。pubsub 的替代方案是 PyDispatcher 模块。
无论如何,在这篇文章中,我们不会研究这些模块背后的理论。相反,我们将在 wxPython 中使用一个半实用的示例来展示如何使用内置版本的 pubsub 在两个框架之间进行通信。如果你还同意我的观点,那么我鼓励你继续读下去! 更新:本文为 wxPython 2.8。如果你碰巧在使用 wxPython 的新版本,那么你会想要阅读我这篇文章的新版本这里
如何在两个框架之间传递信息
我发现有时我需要打开一个非模态框架来获取用户的信息,然后将这些信息传递回应用程序的主框架。其他时候,我只需要告诉我的一个框架,另一个已经关闭。在这两种情况下,pubsub 来拯救。下面的例子将实际演示这两个问题的解决方案。
import wx
from wx.lib.pubsub import Publisher
########################################################################
class OtherFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame")
panel = wx.Panel(self)
msg = "Enter a Message to send to the main frame"
instructions = wx.StaticText(panel, label=msg)
self.msgTxt = wx.TextCtrl(panel, value="")
closeBtn = wx.Button(panel, label="Send and Close")
closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose)
sizer = wx.BoxSizer(wx.VERTICAL)
flags = wx.ALL|wx.CENTER
sizer.Add(instructions, 0, flags, 5)
sizer.Add(self.msgTxt, 0, flags, 5)
sizer.Add(closeBtn, 0, flags, 5)
panel.SetSizer(sizer)
#----------------------------------------------------------------------
def onSendAndClose(self, event):
"""
Send a message and close frame
"""
msg = self.msgTxt.GetValue()
Publisher().sendMessage(("show.mainframe"), msg)
self.Close()
########################################################################
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.frame = parent
Publisher().subscribe(self.showFrame, ("show.mainframe"))
self.pubsubText = wx.TextCtrl(self, value="")
hideBtn = wx.Button(self, label="Hide")
hideBtn.Bind(wx.EVT_BUTTON, self.hideFrame)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.pubsubText, 0, wx.ALL|wx.CENTER, 5)
sizer.Add(hideBtn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(sizer)
#----------------------------------------------------------------------
def hideFrame(self, event):
""""""
self.frame.Hide()
new_frame = OtherFrame()
new_frame.Show()
#----------------------------------------------------------------------
def showFrame(self, msg):
"""
Shows the frame and shows the message sent in the
text control
"""
self.pubsubText.SetValue(msg.data)
frame = self.GetParent()
frame.Show()
########################################################################
class MainFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Pubsub Tutorial")
panel = MainPanel(self)
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
这段代码的第一站是 MainPanel 类。请注意下面一行:
Publisher().subscribe(self.showFrame, ("show.mainframe"))
这创建了一个订阅“show.mainframe”主题的监听器 singleton(又名:接收器)。程序的其他部分可以发布到该主题,监听器将获取它们并调用“showFrame”方法。要了解这一点,请查看“OtherFrame”类的“onSendAndClose”方法。
# OtherFrame Class
def onSendAndClose(self, event):
"""
Send a message and close frame
"""
msg = self.msgTxt.GetValue()
Publisher().sendMessage(("show.mainframe"), msg)
self.Close()
这里,我们获取文本控件的值,并将其发送回主框架。要发送它,我们调用发布者对象的 sendMessage 方法,并向其传递主题字符串和消息。该消息可以是对象列表,也可以只是单个对象。在这种情况下,它只是一个字符串。回到主面板,调用 showFrame 方法。看起来是这样的:
# MainPanel class
def showFrame(self, msg):
"""
Shows the frame and shows the message sent in the
text control
"""
self.pubsubText.SetValue(msg.data)
frame = self.GetParent()
frame.Show()
在这个方法中,我们通过 pubsub 的数据属性提取通过 pubsub 发送的数据。如果我们使用一个列表发送多个条目,我们需要做一些类似 msg.data[0]的事情来获得正确的条目(假设字符串在元素一中)。最新的 pubsub 有一个稍微不同的 API,你可以在它的食谱中查看。最新的 API 是从 wxPython 2.8.11.0 开始提供的。注意:我在用最新的 pubsub 创建二进制文件时遇到了一些麻烦,因为我使用的是稍旧的 API。参见此线程以了解详细信息和一些可能的解决方法。
现在您已经了解了在项目中使用 pubsub 的基本知识。这个例子展示了如何在两个框架之间进行通信,即使其中一个是隐藏的!它还展示了如何将信息从一个框架传递到另一个框架。玩得开心!