【问题标题】:Calling wx.frame class method for handling an events from a button on frame's panel调用 wx.frame 类方法来处理来自框架面板上的按钮的事件
【发布时间】:2020-03-23 17:46:26
【问题描述】:

我有以下类层次结构:

wx.Frame 派生类;在该框架内,我有一个拆分器窗口,以及一个链接到该拆分器窗口的基于 wx.Panel 的类。在面板中,我有一个按钮。我正在将事件处理程序绑定到按钮以执行一些操作。问题是大多数动作都应该在框架类中完成。所以,不知何故,我必须从按钮偶数处理程序中的框架类中调用一个方法。我怎样才能做到这一点?相关部分代码如下。

干杯

class EPSPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        lbl_SGCR = wx.StaticText(self, label="SGCR", pos=(20, 20))
        self.ent_SGCR = wx.TextCtrl(self, value="", pos=(100,20), size=(200,-1))
        lbl_SWCR = wx.StaticText(self, label="SWCR", pos=(20, 60))
        self.ent_SWCR = wx.TextCtrl(self, value="", pos=(100,60), size=(200,-1))
        lbl_SWU = wx.StaticText(self, label="SWU", pos=(20, 100))
        self.ent_SWU = wx.TextCtrl(self, value="", pos=(100,100), size=(200,-1))
        lbl_SGU = wx.StaticText(self, label="SGU", pos=(20, 140))
        self.ent_SGU = wx.TextCtrl(self, value="", pos=(100,140), size=(200,-1))
        lbl_SWL = wx.StaticText(self, label="SWL", pos=(20, 180))
        self.ent_SWL = wx.TextCtrl(self, value="", pos=(100,180), size=(200,-1))
        lbl_SGL = wx.StaticText(self, label="SGL", pos=(20, 220))
        self.ent_SGL = wx.TextCtrl(self, value="", pos=(100,220), size=(200,-1))
        calc_button = wx.Button(self, label="Calculate", pos=(110,260))
        calc_button.Bind(wx.EVT_BUTTON, self.on_btn)

    def on_btn(self, event):
        self.set_SGCR = float(self.ent_SGCR.GetValue())
        self.set_SWCR = float(self.ent_SWCR.GetValue())
        self.set_SGU = float(self.ent_SGU.GetValue())
        self.set_SWU = float(self.ent_SWU.GetValue())
        # these four values in this method I need to pass to the KrFrame class
        # instance to process in one of its methods. I also need somehow
        # let the frame class know that that button was pressed. How can I do it?

class KrFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None,
             title='Gas Relative Permeability Editor', size=(900, 800))
        self.sp = wx.SplitterWindow(self)
        self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
        self.leftSplitter = wx.SplitterWindow(self.sp)
        self.panel01 = KrPanel(self.leftSplitter)
        self.panel02 = PlotPanel(self.rightSplitter)
        self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
        self.panel04 = KrPanel(self.leftSplitter)
        self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
        self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
        self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
        self.create_menu()
        self.Show()

if __name__ == '__main__':
    app = wx.App(False)
    frame = KrFrame()
    app.MainLoop()
    del app

【问题讨论】:

    标签: python events wxpython


    【解决方案1】:

    谢谢罗尔夫。共享代码的问题在于它已经在许多模块上蓬勃发展,共享所有模块将导致几米的滚动。我找到了一种解决方法,如下所示。我的理解是事件在子小部件的所有父类之间传播。因此,如果单击按钮,wxFrame 也会收到事件。因此,我正在绑定到我的 WxFrame 的构造函数下的按钮类的实例。在绑定中,我正在定义事件处理逻辑。这似乎有效:

    class KrFrame(wx.Frame):
        def __init__(self):
            super().__init__(parent=None,
                 title='Gas Relative Permeability Editor', size=(900, 800))
            self.sp = wx.SplitterWindow(self)
            self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
            self.leftSplitter = wx.SplitterWindow(self.sp)
            self.panel01 = KrPanel(self.leftSplitter)
            self.panel02 = PlotPanel(self.rightSplitter)
            self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
    

    这是我将处理程序绑定到按钮单击事件的地方

            self.panel03.calc_button.Bind(wx.EVT_BUTTON, self.on_btn)
            self.panel04 = KrPanel(self.leftSplitter)
            self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
            self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
            self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
            self.create_menu()
            self.Show()
    
        def on_btn(self, event):
            self.set_SGCR = float(self.panel03.ent_SGCR.GetValue())
            self.set_SWCR = float(self.panel03.ent_SWCR.GetValue())
            self.set_SGU = float(self.panel03.ent_SGU.GetValue())
            self.set_SWU = float(self.panel03.ent_SWU.GetValue())
            print(self.set_SGCR, self.set_SWCR, self.set_SGU, self.set_SWU)
    

    【讨论】:

    • 给猫剥皮的方法有很多,这种方法是最好的方法之一:-)
    【解决方案2】:

    您可以调用在框架内定义的函数,但要对数据做一些有用的事情会变得更加困难,因为您已经在一个框架内、一个拆分器窗口内定义了一个拆分器窗口。
    为了将来参考,最好能提供示例代码的运行版本。许多可以回答这个问题的人不希望重新散列代码以使其运行。

    这应该让你深思。

    import wx
    
    class EPSPanel(wx.Panel):
        def __init__(self, parent):
            super().__init__(parent)
    
            #track the real parent for updating purposes
            #
            self.parent = parent.GrandParent
            #
            lbl_SGCR = wx.StaticText(self, label="SGCR", pos=(20, 20))
            self.ent_SGCR = wx.TextCtrl(self, value="", pos=(100,20), size=(200,-1))
            lbl_SWCR = wx.StaticText(self, label="SWCR", pos=(20, 60))
            self.ent_SWCR = wx.TextCtrl(self, value="", pos=(100,60), size=(200,-1))
            lbl_SWU = wx.StaticText(self, label="SWU", pos=(20, 100))
            self.ent_SWU = wx.TextCtrl(self, value="", pos=(100,100), size=(200,-1))
            lbl_SGU = wx.StaticText(self, label="SGU", pos=(20, 140))
            self.ent_SGU = wx.TextCtrl(self, value="", pos=(100,140), size=(200,-1))
            lbl_SWL = wx.StaticText(self, label="SWL", pos=(20, 180))
            self.ent_SWL = wx.TextCtrl(self, value="", pos=(100,180), size=(200,-1))
            lbl_SGL = wx.StaticText(self, label="SGL", pos=(20, 220))
            self.ent_SGL = wx.TextCtrl(self, value="", pos=(100,220), size=(200,-1))
            calc_button = wx.Button(self, label="Calculate", pos=(110,260))
            calc_button.Bind(wx.EVT_BUTTON, self.on_btn)
    
        def on_btn(self, event):
            self.set_SGCR = float(self.ent_SGCR.GetValue())
            self.set_SWCR = float(self.ent_SWCR.GetValue())
            self.set_SGU = float(self.ent_SGU.GetValue())
            self.set_SWU = float(self.ent_SWU.GetValue())
            # these four values in this method I need to pass to the KrFrame class
            # instance to process in one of its methods. I also need somehow
            # let the frame class know that that button was pressed. How can I do it?
    
            KrFrame.mycalculation(self.parent,self.set_SGCR,self.set_SWCR,self.set_SGU,self.set_SWU)
    
    class KrFrame(wx.Frame):
        def __init__(self):
            super().__init__(parent=None,
                 title='Gas Relative Permeability Editor', size=(900, 800))
            self.sp = wx.SplitterWindow(self)
            self.rightSplitter = wx.SplitterWindow(self.sp) #Another splitter to split right panel into two vertical ones
            self.leftSplitter = wx.SplitterWindow(self.sp)
            self.panel01 = wx.Panel(self.leftSplitter)
    
            self.Total = wx.TextCtrl(self.panel01)
    
            self.panel02 = wx.Panel(self.rightSplitter)
            self.panel03 = EPSPanel(self.rightSplitter) #Third panel for scaled end point entry
            self.panel04 = wx.Panel(self.leftSplitter)
            self.rightSplitter.SplitHorizontally(self.panel02, self.panel03, 400) #Splitting right panel into two horizontally
            self.leftSplitter.SplitHorizontally(self.panel01, self.panel04, 400)
            self.sp.SplitVertically(self.leftSplitter, self.rightSplitter, 450)
    #        self.create_menu()
            self.Total.SetValue("00000.00")
            self.Show()
    
        def mycalculation(parent,SGCR=0,SWCR=0,SGU=0,SWU=0):
            print ("Total of values:",SGCR,SWCR,SGU,SWU,"=",SGCR+SWCR+SGU+SWU)
            parent.Total.SetValue(str(SGCR+SWCR+SGU+SWU))
    
    
    if __name__ == '__main__':
        app = wx.App(False)
        frame = KrFrame()
        app.MainLoop()
    

    【讨论】:

    • 谢谢罗尔夫。共享代码的问题在于它已经在许多模块上蓬勃发展,并且共享所有模块将导致几米的滚动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多