【问题标题】:wxPython: Class attribute shared among several instances accidentallywxPython:在多个实例之间意外共享的类属性
【发布时间】:2013-11-27 03:18:53
【问题描述】:

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

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

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

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,我被打印出来:设置 {'Delay': '1.0e-3', 'Width': '10.0e-6', '尾随':'1.0e-6','领先':u'1'}

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

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

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

【问题讨论】:

    标签: python oop inheritance wxpython


    【解决方案1】:

    您正在处理消息EVT_TEXT_ENTER,而on_change_pulses 仅使用修改事件的TextCtrl 的值更新self.data

    您可以通过处理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
    

    【讨论】:

    • 谢谢!那成功了。我最终使用了第二个版本,因为它更明确且更易于阅读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 2015-09-11
    • 1970-01-01
    • 2012-12-17
    相关资源
    最近更新 更多