背景:10个输入对象,每个对象对应一个滑块slider控件和文本框textctrl控件,用户拉动对应输入对象的滑块后,滑块的数值会显示在滑块控件下方的文本框内,这10个滑块的响应事件函数本质是功能是一样的,只是对应输入的滑块控件名称和文本框控件名称不同。现在期望实现的功能是避免重复定义相似功能的函数,当输入对象的个数变化不是10个时,滑块的响应事件执行函数能够根据输入对象个数相应的获取对应的滑块slider控件和文本框textctrl控件。
原程序代码:
# 拉动滑块事件
self.m_slider1.Bind(wx.EVT_SCROLL, self.get_item1_value)
self.m_slider2.Bind(wx.EVT_SCROLL, self.get_item2_value)
self.m_slider3.Bind(wx.EVT_SCROLL, self.get_item3_value)
self.m_slider4.Bind(wx.EVT_SCROLL, self.get_item4_value)
self.m_slider5.Bind(wx.EVT_SCROLL, self.get_item5_value)
self.m_slider6.Bind(wx.EVT_SCROLL, self.get_item6_value)
self.m_slider7.Bind(wx.EVT_SCROLL, self.get_item7_value)
self.m_slider8.Bind(wx.EVT_SCROLL, self.get_item8_value)
self.m_slider9.Bind(wx.EVT_SCROLL, self.get_item9_value)
self.m_slider10.Bind(wx.EVT_SCROLL, self.get_item10_value)
def get_item1_value(self, event):
item_value = self.m_slider1.GetValue() # 返回int
self.m_textCtrl2.SetValue(str(item_value))
def get_item2_value(self, event):
item_value = self.m_slider2.GetValue() # 返回int
self.m_textCtrl3.SetValue(str(item_value))
def get_item3_value(self, event):
item_value = self.m_slider3.GetValue() # 返回int
self.m_textCtrl4.SetValue(str(item_value))
def get_item4_value(self, event):
item_value = self.m_slider4.GetValue() # 返回int
self.m_textCtrl5.SetValue(str(item_value))
def get_item5_value(self, event):
item_value = self.m_slider5.GetValue() # 返回int
self.m_textCtrl6.SetValue(str(item_value))
def get_item6_value(self, event):
item_value = self.m_slider6.GetValue() # 返回int
self.m_textCtrl7.SetValue(str(item_value))
def get_item7_value(self, event):
item_value = self.m_slider7.GetValue() # 返回int
self.m_textCtrl8.SetValue(str(item_value))
def get_item8_value(self, event):
item_value = self.m_slider8.GetValue() # 返回int
self.m_textCtrl9.SetValue(str(item_value))
def get_item9_value(self, event):
item_value = self.m_slider9.GetValue() # 返回int
self.m_textCtrl10.SetValue(str(item_value))
def get_item10_value(self, event):
item_value = self.m_slider10.GetValue() # 返回int
self.m_textCtrl11.SetValue(str(item_value))
解决办法:可以将参数传递给事件处理程序,可以使用lambda: …来完成。
第一次尝试修改:
# 拉动滑块事件
for i in range(len(item_list)):
param = [self.set_slider_dict(i), self.set_itemtextctrl_dict(i)]
self.set_slider_dict(i).Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
def set_slider_dict(self, idx):
slider_list = [self.m_slider1, self.m_slider2, self.m_slider3, self.m_slider4, self.m_slider5,
self.m_slider6, self.m_slider7, self.m_slider8, self.m_slider9, self.m_slider10]
slider_dict = {}
for i in range(len(item_list)):
slider_dict[i] = slider_list[i]
return slider_dict[idx]
def set_itemtextctrl_dict(self, idx):
textctrl_list = [self.m_textCtrl2, self.m_textCtrl3, self.m_textCtrl4, self.m_textCtrl5,
self.m_textCtrl6, self.m_textCtrl7, self.m_textCtrl8, self.m_textCtrl9,
self.m_textCtrl10, self.m_textCtrl11]
textctrl_dict = {}
for i in range(len(item_list)):
textctrl_dict[i] = textctrl_list[i]
return textctrl_dict[idx]
def get_item_value(self, event, param):
item_value = param[0].GetValue() # 返回int
print("item_value", item_value)
param[1].SetValue(str(item_value))
修改无效,10个滑块同时响应的是最后一个滑块的滑块拉动数值。得到的结论是不能采用for循环的方式为每一个滑块定义相同的触发事件函数。
第二次尝试修改:
param = [self.set_slider_dict(0), self.set_itemtextctrl_dict(0)]
self.m_slider1.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(1), self.set_itemtextctrl_dict(1)]
self.m_slider2.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(2), self.set_itemtextctrl_dict(2)]
self.m_slider3.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(3), self.set_itemtextctrl_dict(3)]
self.m_slider4.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(4), self.set_itemtextctrl_dict(4)]
self.m_slider5.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(5), self.set_itemtextctrl_dict(5)]
self.m_slider6.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(6), self.set_itemtextctrl_dict(6)]
self.m_slider7.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(7), self.set_itemtextctrl_dict(7)]
self.m_slider8.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(8), self.set_itemtextctrl_dict(8)]
self.m_slider9.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
param = [self.set_slider_dict(9), self.set_itemtextctrl_dict(9)]
self.m_slider10.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param))
同样修改无效,10个滑块同时响应的是最后一个滑块的滑块拉动数值。得到的结论是目前该种方式不能实现需求。分析发现是由于每个滑块控件的响应事件函数get_item_value()的输入参数都是取的最后一个param输入。
第三次尝试修改:
param1 = [self.set_slider_dict(0), self.set_itemtextctrl_dict(0)]
self.m_slider1.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param1))
param2 = [self.set_slider_dict(1), self.set_itemtextctrl_dict(1)]
self.m_slider2.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param2))
param3 = [self.set_slider_dict(2), self.set_itemtextctrl_dict(2)]
self.m_slider3.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param3))
param4 = [self.set_slider_dict(3), self.set_itemtextctrl_dict(3)]
self.m_slider4.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param4))
param5 = [self.set_slider_dict(4), self.set_itemtextctrl_dict(4)]
self.m_slider5.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param5))
param6 = [self.set_slider_dict(5), self.set_itemtextctrl_dict(5)]
self.m_slider6.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param6))
param7 = [self.set_slider_dict(6), self.set_itemtextctrl_dict(6)]
self.m_slider7.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param7))
param8 = [self.set_slider_dict(7), self.set_itemtextctrl_dict(7)]
self.m_slider8.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param8))
param9 = [self.set_slider_dict(8), self.set_itemtextctrl_dict(8)]
self.m_slider9.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param9))
param10 = [self.set_slider_dict(9), self.set_itemtextctrl_dict(9)]
self.m_slider10.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param10))
代码修改之后功能测试ok。
完整代码:
# 拉动滑块事件
param1 = [self.set_slider_dict(0), self.set_itemtextctrl_dict(0)]
self.m_slider1.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param1))
param2 = [self.set_slider_dict(1), self.set_itemtextctrl_dict(1)]
self.m_slider2.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param2))
param3 = [self.set_slider_dict(2), self.set_itemtextctrl_dict(2)]
self.m_slider3.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param3))
param4 = [self.set_slider_dict(3), self.set_itemtextctrl_dict(3)]
self.m_slider4.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param4))
param5 = [self.set_slider_dict(4), self.set_itemtextctrl_dict(4)]
self.m_slider5.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param5))
param6 = [self.set_slider_dict(5), self.set_itemtextctrl_dict(5)]
self.m_slider6.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param6))
param7 = [self.set_slider_dict(6), self.set_itemtextctrl_dict(6)]
self.m_slider7.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param7))
param8 = [self.set_slider_dict(7), self.set_itemtextctrl_dict(7)]
self.m_slider8.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param8))
param9 = [self.set_slider_dict(8), self.set_itemtextctrl_dict(8)]
self.m_slider9.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param9))
param10 = [self.set_slider_dict(9), self.set_itemtextctrl_dict(9)]
self.m_slider10.Bind(wx.EVT_SCROLL, lambda evt: self.get_item_value(evt, param10))
def set_slider_dict(self, idx):
slider_list = [self.m_slider1, self.m_slider2, self.m_slider3, self.m_slider4, self.m_slider5,
self.m_slider6, self.m_slider7, self.m_slider8, self.m_slider9, self.m_slider10]
slider_dict = {}
for i in range(len(item_list)):
slider_dict[i] = slider_list[i]
return slider_dict[idx]
def set_itemtextctrl_dict(self, idx):
textctrl_list = [self.m_textCtrl2, self.m_textCtrl3, self.m_textCtrl4, self.m_textCtrl5,
self.m_textCtrl6, self.m_textCtrl7, self.m_textCtrl8, self.m_textCtrl9,
self.m_textCtrl10, self.m_textCtrl11]
textctrl_dict = {}
for i in range(len(item_list)):
textctrl_dict[i] = textctrl_list[i]
return textctrl_dict[idx]
def get_item_value(self, event, param):
item_value = param[0].GetValue() # 返回int
param[1].SetValue(str(item_value))
小结:目前修改之后的程序还是没有很好的实现“当输入对象的个数变化不是10个时,滑块的触发事件执行函数能够根据输入对象个数相应的获取对应的滑块slider控件和文本框textctrl控件“这个需求,滑块的响应事件设置还是需要一个个的手动设置,不能根据输入对象的个数实时变动。
参考链接:
https://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks
【wxpython】Bind绑定带不定参
wxPython-多个按钮使用同一个回调函数