【问题标题】:getting parts of a wxpython program to communicate with one another让 wxpython 程序的一部分相互通信
【发布时间】:2014-02-21 07:31:17
【问题描述】:

因此,在编写了一堆小型的个人 wxPython 应用程序之后,我决定将程序组织成一系列 wx.Panel(),如下所示:

class display(wx.Panel):
    <buttons, sliders, etc>
    <sizer>
...
class selector(wx.Panel):
    <buttons and stuff>
    <sizer>
...

然后我将这些面板放入一个框架中,作为主面板的子级,此时我可以使用像这样的尺寸器进行组织:

class mainwindow(wx.Frame):
    master_panel = wx.Panel()
    display = display(master_panel)
    selector = selector(master_panel)

    <sizers and stuff>

我现在的问题是两个面板需要某种方式相互通信。例如,当在选择器中单击某些内容(如文件名)时,显示需要相应更新。

首先想到的是使用现有的事件系统来创建我自己的自定义事件,然后将它们绑定到每个面板中的处理程序,但我不太确定这是正确的方法。我决定将 Panel() 子类化是否造成了我本来不会遇到的问题,还是有更好的方法来处理这个面板间通信问题?

【问题讨论】:

    标签: python-2.7 wxpython


    【解决方案1】:

    使用 pubsub 模块。它为您提供了几乎您所描述的自己所做的事情:一种使用从一个模块到另一个模块的事件发出信号的方法。它的优点是您不必在发送者和接收者之间建立连接 - 接收者只需声明它想要收听某些类型的消息并且......宾果游戏......它会得到它们。

    from wx.lib.pubsub import pub
    
    class display(wx.Panel):
        def __init__(self,... whatever):
            <buttons, sliders, etc>
            <sizer>
            pub.subscribe("SELECTION_INFO", self.OnSelection)
    
        def OnSelection(self, info):
            # do stuff with info 
    
    ...
    class selector(wx.Panel):
        def __init__(self, ... whatever)
            <buttons and stuff>
            <sizer>
    
        def OnSomeButtonPressed(self, event):
            pub.SendMessage("SELECTION_INFO", info="some useful info about what was pressed")
    
    ...
    

    请注意,您不需要让主窗口参与其子级之间的通信。

    【讨论】:

    • 这正是我所需要的。我实际上去单独下载了模块,只是注意到它实际上包含在 wxPython 中......
    • 需要注意的一点:虽然接口语义暗示 pubsub 是基于事件的,但实际上它不是基于事件的,就 wx 事件而言。当您调用 SendMessage 时,在您的 SendMessage 调用返回之前,执行流程一直通过订阅者的代码。 FWIW - 当我发现它时,这让我大吃一惊,尽管大多数时候你不会在意。
    【解决方案2】:

    您可以使用知道所有子面板的父面板在它们之间进行调解,当子面板引发事件(标准或自定义事件)时,父面板绑定一个事件处理程序,该处理程序调用其他面板上的方法相应地更新它们。

    他是你的伪代码中添加的一些伪代码

    class display(wx.Panel):
        def __init__(self, *args, **kwargs):
            super(display, self).__init__(*args, **kwarg)
            <buttons, sliders, etc>
            <sizer>
    
        def do_some_update(self):
            <update>
    ...
    class selector(wx.Panel):
        def __init__(self, *args, **kwargs):
            super(selector, self).__init__(*args, **kwargs)
            <buttons and stuff>
            <sizer>
    ...
    
    
    class mainwindow(wx.Frame):
        def __init__(self, *args, **kwargs):
            super(mainwindow, self).__init__(*args, **kwargs)
            master_panel = wx.Panel()
            self.display = display(master_panel)
            self.selector = selector(master_panel)
    
            <sizers and stuff>
    
            self.selector.button.Bind(wx.EVT_BUTTON, self.on_button_pressed)
    
        def on_button_pressed(self, event):
            self.display.do_some_update()
    

    注意:这类似于我之前回答过的一些问题

    wx.Python: Passing control between multiple panels

    Passing a tuple between two Panels in wxPython

    【讨论】:

    • 明确“谁应该拥有这个逻辑”很重要?在此解决方案中,您的设计是“谁做什么”的所有逻辑都由 MainWindow 拥有的设计 - 一种集中式设计,并且如果子项的实现发生更改,则 MainWindow 中的代码必须更改。相比之下,pubsub 解决方案提供了关注点分离 - 需要处理事件的子进程负责,并且信号机制与子 gui 的实现分离。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多