2013-11-27 25 views
0

这段代码让我挠了挠头。wxPython:意外地在几个实例之间共享的类属性

我想写wxPython的图形用户界面,与包含几个“PulseBox”对象(下面的代码)的框架。每个脉冲盒基本上都是4个wx.TextCtrls,其中4个wx.StaticTexts作为标签放在它们旁边。该对象有一个名为'data'的属性,这是我希望稍后访问的字典。

我想TextCtrls输入文本时改变“数据”的价值观为自己的脉搏框。 Unfortunatley,当我将文本输入到一个脉冲盒时,它现在正在改变所有脉冲盒的“数据”。

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() 

作为一个例子,当我改变 '设置' 框

到1的 '龙头' TextCtrl,我得到印刷:集{ '延时': '1.0E-3' '宽':'10 .0e-6' , '尾随': '1.0E-6', '领导':U'' }

,然后当我改变的 '宽度' TextCtrl '重置'框为2,我得到了打印:

复位{ '延时': '1.0E-3', '宽度':U'2' , '尾随': '1.0E-6', '龙头':U'1' }

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

回答

0

您正在处理消息EVT_TEXT_ENTERon_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 
+0

谢谢!那就是诀窍。我最终使用了第二个版本,因为它更明确,更易于阅读。 – jengel