帮助在wxDesigner面板的克隆副本中引用小部件

时间:2011-03-19 11:32:07

标签: wxpython

我是wx.python编程的新手,我在完成目标时遇到了麻烦。我正在设计一个程序来检查特定文件特征的目录,并将有关目录和文件的信息返回给用户。然后,用户将为每个目录做出选择。这些选择被传递回控制程序。 因为为每个x目录呈现给用户的信息格式是相同的,所以我在wxDesigner中创建了面板以显示这些信息并与之交互。这些面板被插入x次多次进入滚动面板。 (我相信wxDesigner实际上会在滚动面板中返回插入主sizer的父sizer。)到目前为止一直很好......

当我尝试访问出现的不同表单时,我的麻烦就开始了。因为我正在插入在wxDesigner中创建的表单,所以ID被分配一次并应用于表单的所有副本。由于我正在插入整个表单的副本,因此我无法为每个重复字段创建单独的ID,正如我在许多示例中所做的那样(在我搜索网络的几个小时内)创建并插入了多个小部件在运行时进入面板。

我在迭代循环中添加表单。我试图给插入表单的实例分别命名,我已经使用SetId(),NewId()等重新分配了ID而没有运气。我也尝试过使用SetName(),但在这两种方法中,我最后都会在最后插入的表单上分配ID或名称,引用所有表单上所有匹配的小部件。

我遇到了无数的死胡同,接下来想到在插入wxDesigner对象时创建单独的面板。但是,只有当我能够通过parent.widget引用一个小部件时,这才有效,而且我还没有看到任何这样做的例子。我还想过在wxDesigner xxx_wdr.py文件中写一个过程(一旦我知道它不会改变),它为每个插入的实例生成单独的ID。但是在我再次撞墙之前,我想我会请求帮助知道要去哪个方向......

如果这是一个小细节问题,我可以展示我的代码(许多尝试的一个版本),但让我们开始对这种情况下的一般方法提出建议。任何帮助将不胜感激。谢谢,

3 个答案:

答案 0 :(得分:1)

感谢您的建议,绝对有用的信息!我无法使用类面板方法,因为我无法编辑wxPython生成的代码,但看看它是如何完成的很有用。

我的解决方案是通过SetId()将我的代码中的静态Id重新分配给由特定小部件的固定ID组成的数字,加上插入表单的迭代次数。这为每个窗口小部件/窗体创建了一个唯一的ID。我使用了一个字典(谢谢,Mike)来查找id的基本部分,并且可以随时附加迭代计数来引用它们。我使用一个过程来简化查找小部件ID,所以我不需要重复输入'FindWindow ....'位。可能有更优雅的方式,但这有效:

        widgetId = {
        'btn' : 6000,
        'textctrl' : 6010,
        'textlbl' :6020 }

    def getWidget(self, widget, formNo ):
        '''Finds widget window via lookup of re-assigned widget ID #'s'''
        widget = self.FindWindowById(self.widgetId[widget] + formNo)
        return widget

    def cloneWX(self):
        '''Reassign ID at time of cloning'''
        for  formNo in range(self.clones):
            # Insert the cloned form (a BoxSizer created by wxDesigner) into this copy:
            self.form = NewDialog( self.panel1, True, set_sizer = False)
            self.grid.Add(self.form, flag=wx.RIGHT, border=10)

            # Set initial references:
            self.textlbl = self.FindWindowById( ID_TEXT )
            self.textctrl = self.FindWindowById( ID_TEXTCTRL)
            self.btn = self.FindWindowById( ID_BUTTON_1 )

            # Reset ID based on form number: (Can reference via dictionary instead))
            self.btn.SetId(6000 + formNo)
            self.textctrl.SetId(6010 + formNo)
            self.textlbl.SetId(6020 + formNo)

            # Bind events to new ID references:
            wx.EVT_BUTTON(self, 6000 + formNo, self.OnBtn)

    def OnBtn(self, event):
        event_object = event.GetEventObject()
        # From the event id, extract the form number where this widget appears :
        formNo = event_object.GetId() - self.widgetId['btn']

        textctrl = self.getWidget('textctrl', formNo)
        textlbl = self.getWidget('textlbl', formNo)
        textlbl.SetLabel(textctrl.GetValue())

答案 1 :(得分:0)

我不熟悉wxDesigner,但是如果你有相同wx.Panel(或任何东西)的多个相同副本,最好将它们添加到listdict当你将它们添加到主表单时。这将允许您单独访问它们以及它们的任何子项(通过您提到的parent.widget)。您还可以使用访问器函数将面板包装在您自己的类中,以便从类外部检索值,而无需直接调用窗口小部件。

伪代码:

class CustomPanel:
    def __init__(self, parent, etc):
        GeneratedPanel.__init__(self, parent, etc)

    def GetFirstThing(self):
        return self.FirstThing.GetValue()

    def GetSecondThing(self):
        return self.SecondThing.GetValue()

class MainWindow:
    def __init__(self, parent, etc)
        #...
        self.panels = []
        for i in range(10):
            self.panels.append(CustomPanel(self, etc))

    def GetSomeValue(self, index):
        return self.panels[index].GetFirstThing()

答案 2 :(得分:0)

您应该能够用wx.ID_ANY替换id行代码。此外,您可以在实例化时设置窗口小部件的名称。这是一个例子:

btn = wx.Button(parent,name =“myBtn”)

如果您需要从其父级获取子窗口小部件,那么您将必须执行以下操作:

children = parent.GetChildren()

for child in children:
   if child.GetName() == "someName":  # or child.GetId() or whatever
      # do something here

我不知道这是否会对你有所帮助。