我在wxPython中为I2C设备编写了一个稍大的GUI应用程序。程序启动时,它会从XML文件动态生成设备菜单。首先为每个类型附加一个子菜单'设备(EEPROM,多路复用器,IOExpander等),然后在每个子菜单中,附加实际设备的名称。由于菜单在运行时尚未创建,因此我必须动态分配ID。此外,因为XML文件将不时更新新的"类型"对于设备,我不仅要知道选择了哪个项目,还要知道项目来自哪个子菜单。我实现这一目标的当前方式是拥有一个父母和孩子。 ID I中的关系分配项目。目前,其中一个菜单项的ID是一个3位数字:第一个数字总是2,所以我知道它来自设备菜单。第二个数字是选择来自的子菜单,最后一个数字是选择的特定设备。为了存储这些ID,我将它们添加到字典中,其中ID是密钥,设备的名称是值。
submenu_id = -1
for device_type in self.device_list:
submenu = wx.Menu()
submenu_id += 1
device_menu_id = -1
for device in device_type.m_device_list:
device_menu_id += 1
device_id = 200 + (submenu_id * 10) + device_menu_id
id_list[device_id] = device.m_name
item = wx.MenuItem(submenu, device_id, device.m_name, wx.EmptyString, wx.ITEM_NORMAL)
submenu.AppendItem(item)
menu.AppendSubMenu(submenu, device_type.m_name)
现在,我有两个问题。最直接的问题是我需要保留200到299的ID范围,其中包含可以分配给设备项的所有可能的ID。如果我调用wx.ID_ANY,它有时会在该范围内为其他菜单分配ID,这意味着我的绑定都搞砸了。另一个问题是,我认为这是一种人为的方式。目前,我只能有10种不同类型的设备子菜单,每个子菜单中只有10个设备。在可预见的未来,这应该足够了,但是我希望能够在尽可能多的不同类别中添加尽可能多的设备。此外,执行此操作的代码非常难看并且模糊不清,我非常希望有人阅读我的代码以了解我正在做什么。
所以,我的第一个问题是:有没有办法保留我需要的ID范围,所以我不会与wx发生任何冲突?
我的第二个问题是,还有更好的方法吗?
答案 0 :(得分:0)
请参阅wx.RegisterId(id)
。简而言之,wx.NewId
非常简单。它只是递增内部计数器并返回值而没有额外的智能。如果您使用wx.RegisterId(id)
,那么该计数器将设置为给定的值,以便wx.NewId
返回的下一个计数器将是> ID。因此,您可以将其设置为某个值,然后低于该值的所有内容(尚未为系统ID保留,如wx.ID_OK)可以用作代码的显式ID。但请注意,如果您在应用程序运行的整个生命周期中使用数千个wx.ID_ANY
或wx.NewID()
ID,则自动ID可能会回滚。
至于更好的方法,我想我会使用wx.ID_ANY
然后使用字典将分配给项目的菜单ID映射到真实数据对象。这样,ID(实际上只是与UI关联的实现细节,而不是数据模型)本身没有实际意义,但它们可以在菜单事件处理程序中使用,以轻松获取相关的实际数据到申请。例如:
item = menu.Append(wx.ID_ANY, "Foo")
self.menuIdMap[item.GetId()] = someDataObjectForFoo
self.Bind(wx.EVT_MENU, self.OnMenuItemSelected, item)
然后:
def OnMenuItemSelected(self, evt):
dataObj = self.menuIdMap[evt.GetId()]
dataObj.doSomething()