wxPython:意外地在几个实例之间共享的类属性

时间:2013-11-27 03:18:53

标签: python oop inheritance wxpython

这段代码让我摸不着头脑。

我正在尝试编写wxPython GUI,其框架包含几个'PulseBox'对象(下面的代码)。每个脉冲盒基本上是4个wx.TextCtrls,其中4个wx.StaticTexts位于它们旁边作为标签。该对象有一个名为“data”的属性,这是一个我想稍后访问的字典。

我希望TextCtrls在输入文本时更改自己的脉冲框的'data'值。不幸的是,当我将文本输入单个脉冲盒时,它现在正在改变所有脉冲盒的“数据”。

import wx

class MainGUI(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, '')

        self.panel = wx.Panel(self)

        #Create Controls
        #All Contained in a Static Box       
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)        

        #A Row of Pulseboxes
        self.setpulse = PulseBox(self.panel, 'Set')
        self.resetpulse = PulseBox(self.panel, 'Reset')
        self.gatepulse = PulseBox(self.panel, 'Gate')

        #Generate Layout
        #Use a FlexGrid Sizer
        self.fgs = wx.FlexGridSizer(rows=1, cols=3, vgap=15, hgap=15)

        self.fgs.AddMany([(self.setpulse, 1, wx.EXPAND),
            (self.resetpulse, 1, wx.EXPAND),
            (self.gatepulse, 1, wx.EXPAND)])

        #Add the FlexGridSizer to the StaticBoxSizer
        self.sizer.Add(self.fgs, proportion=1, flag=wx.ALL, border=15)

        #FitTheSizer
        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)



class PulseBox(wx.Panel):

    def __init__(self, parent, name='Set', 

        data=dict(Leading='1.0e-6', Width='10.0e-6',
            Trailing='1.0e-6', Delay='1.0e-3') ):

        wx.Panel.__init__(self, parent)
        self.data = data
        self.name = name

        #Create Controls
        #All Contained in a Static Box       
        self.box = wx.StaticBox(self, label=name + ' Pulse (seconds)')
        self.sizer = wx.StaticBoxSizer(self.box, wx.VERTICAL)        

        #A row of labels
        self.label_lead = wx.StaticText(self, label='Leading')
        self.label_width = wx.StaticText(self, label='Width')
        self.label_trail = wx.StaticText(self, label='Trailing')
        self.label_delay = wx.StaticText(self, label='Delay')

        #A row of textctrls
        self.textctrl_lead = wx.TextCtrl(self, value=data['Leading'], style=wx.TE_PROCESS_ENTER, name='Leading')
        self.textctrl_width = wx.TextCtrl(self, value=data['Width'], style=wx.TE_PROCESS_ENTER, name='Width')
        self.textctrl_trail = wx.TextCtrl(self, value=data['Trailing'], style=wx.TE_PROCESS_ENTER, name='Trailing')
        self.textctrl_delay = wx.TextCtrl(self, value=data['Delay'], style=wx.TE_PROCESS_ENTER, name='Delay')

        #Send back their data
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_width)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_lead)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_trail)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_delay)


        #Generate Layout
        #Use a FlexGrid Sizer
        self.fgs = wx.FlexGridSizer(rows=4, cols=2, vgap=9, hgap=25)

        self.fgs.AddMany([(self.label_lead), (self.textctrl_lead, 1, wx.EXPAND),
            (self.label_width), (self.textctrl_width, 1, wx.EXPAND),
            (self.label_trail), (self.textctrl_trail, 1, wx.EXPAND),
            (self.label_delay), (self.textctrl_delay, 1, wx.EXPAND)])

        #Expand the TextCtrl boxes to fill panel
        self.fgs.AddGrowableCol(1, 1)

        #Add the FlexGridSizer to the StaticBoxSizer
        self.sizer.Add(self.fgs, proportion=1, flag=wx.ALL|wx.EXPAND, border=15)

        #FitTheSizer
        self.SetSizer(self.sizer)
        self.sizer.Fit(self)

    def on_change_pulses(self, event):
        textctrl = event.GetEventObject()
        name = textctrl.GetName()
        value = textctrl.GetValue()

        self.data[name] = value

        print self.name, self.data

if __name__ == '__main__':
    app = wx.PySimpleApp()
    app.frame = MainGUI()
    app.frame.Show()
    app.MainLoop()

例如,当我更改'Set'框的'Leading'TextCtrl时

  

到1,我打印出来:设置{'延迟':'1.0e-3','宽度':'10 .0e-6',   '尾随':'1.0e-6','领先':u'1'}

然后当我将'重置'框的'宽度'TextCtrl更改为2时,我会打印出来:

  

重置{'延迟':'1.0e-3','宽度':u'2','尾随':'1.0e-6',   '领先':u'1'}

即使我从未为重置框设置'前导'。

1 个答案:

答案 0 :(得分:0)

您正在处理邮件EVT_TEXT_ENTER,而on_change_pulses仅更新self.data,其值为TextCtrl修订了该事件。

您可以通过处理EVT_TEXT来修复它,以便在用户修改某些TextCtrl后立即更新这些值,您可以添加:

        ....
        #Send back their data
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_width)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_lead)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_trail)
        self.Bind(wx.EVT_TEXT_ENTER, self.on_change_pulses, self.textctrl_delay)

        # ADDED: listen for EVT_TEXT event
        self.Bind(wx.EVT_TEXT, self.on_change_pulses_update, self.textctrl_width)
        self.Bind(wx.EVT_TEXT, self.on_change_pulses_update, self.textctrl_lead)
        self.Bind(wx.EVT_TEXT, self.on_change_pulses_update, self.textctrl_trail)
        self.Bind(wx.EVT_TEXT, self.on_change_pulses_update, self.textctrl_delay)

        #Generate Layout
        #Use a FlexGrid Sizer
        self.fgs = wx.FlexGridSizer(rows=4, cols=2, vgap=9, hgap=25)
        ....

并为事件添加处理程序:

    def on_change_pulses_update(self, event):
        textctrl = event.GetEventObject()
        name = textctrl.GetName()
        value = textctrl.GetValue()

        self.data[name] = value

或者,如果其中任何人修改TextCtrl,您可以重新阅读所有EVT_TEXT_ENTER的值:

    def on_change_pulses(self, event):
        textctrl = event.GetEventObject()
        name = textctrl.GetName()
        #value = textctrl.GetValue()

        self.data['Width']    = self.textctrl_width.GetValue()
        self.data['Leading']  =  self.textctrl_lead.GetValue()
        self.data['Trailing'] = self.textctrl_trail.GetValue()
        self.data['Delay']    =  self.textctrl_delay.GetValue()

        print self.name, self.data