【问题标题】:Generate List of All sizerItems Nested in wxPython Sizers生成嵌套在 wxPython Sizer 中的所有 sizerItem 的列表
【发布时间】:2013-12-04 19:49:46
【问题描述】:

我正在寻找一种方法来获取与小部件相对应的所有sizerItems 的列表。为了演示,我创建了以下示例:

import wx
from wx.lib.scrolledpanel import ScrolledPanel 

class Tester(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Window")
        self.panel = ScrolledPanel(parent=self, id=-1)
        self.panel.SetupScrolling()
        self.sizerItems = []

        Btn1 = wx.Button(self.panel, -1, "I'm a Button!") 
        Btn2 = wx.Button(self.panel, -1, "Me Too!") 
        Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!") 
        Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax") 


        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)

        hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
        hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
        hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
        hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)

        vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
        vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)

        self.panel.SetSizer(vbox)
        self.panel.Layout()

        self.GetAllChildren(self.panel.GetSizer())
        print self.sizerItems


    def GetAllChildren(self, item):
        try:
            for sizerItem in item.GetChildren():
                self.GetAllChildren(sizerItem)
        except:
            try: 
                item.GetSizer()
                self.GetAllChildren(item.GetSizer())
            except:
                self.sizerItems.append(item)
                return


app = wx.PySimpleApp()
Tester().Show()
app.MainLoop()

这段代码创建了一个带有 4 个按钮的 GUI。我希望GetAllChildren() 返回所有不是sizer 的sizerItems 的列表(self.sizerItems)。对于此示例,列表中应该有 4 个元素对应于四个按钮。 GetAllChildren() 应该递归地沿着 sizers 树向下运行,所以首先是 vbox,然后是 hbox1 及其所有子节点,然后是 hbox2 及其所有子节点。

目前,我得到[None,None,None,None] 作为结果。我意识到try...except 是它正在破坏的地方,但我不知道如何确定某个特定项目是否是我想要的。有关如何解决此问题或替代方法的任何建议?提前致谢

【问题讨论】:

    标签: python python-2.7 wxpython


    【解决方案1】:

    我对代码进行了一些修改并对其进行了更改,以便它实际上返回小部件实例而不是 sizerItem 实例:

    import wx
    from wx.lib.scrolledpanel import ScrolledPanel 
    
    class Tester(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, -1, "Window")
            self.panel = ScrolledPanel(parent=self, id=-1)
            self.panel.SetupScrolling()
            self.sizerItems = []
    
            Btn1 = wx.Button(self.panel, -1, "I'm a Button!") 
            Btn2 = wx.Button(self.panel, -1, "Me Too!") 
            Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!") 
            Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax") 
    
    
            vbox = wx.BoxSizer(wx.VERTICAL)
            hbox1 = wx.BoxSizer(wx.HORIZONTAL)
            hbox2 = wx.BoxSizer(wx.HORIZONTAL)
    
            hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
            hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
            hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
            hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
    
            vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
            vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
    
            self.panel.SetSizer(vbox)
            self.panel.Layout()
    
            self.GetAllChildren(self.panel.GetSizer())
            print self.sizerItems
    
        def GetAllChildren(self, item):
            for sizerItem in item.GetChildren():
                widget = sizerItem.GetWindow()
                if not widget:
                    # then it's probably a sizer
                    sizer = sizerItem.GetSizer()
                    if isinstance(sizer, wx.Sizer):
                        self.GetAllChildren(sizer)
                else:
                    self.sizerItems.append(widget)
    
    #----------------------------------------------------------------------
    if __name__ == "__main__":
        app = wx.App(False)
        Tester().Show()
        app.MainLoop()
    

    您可以在我的一个旧教程中阅读有关此方法的更多信息:

    这很奇怪,是基于另一个 StackOverflow 问题:

    无论如何,当我运行上面的代码时,我得到了一个包含四个按钮的列表。为了检查并确保它们不是添加了 4 次的同一个按钮,我这样做了:

    for item in self.sizerItems: 
        print item.GetLabel()
    

    您可能还想看看小部件检查工具,它可以直观地向您显示哪些小部件在哪些尺寸器中。

    【讨论】:

    • 很棒,效果很好。我想我打算在获得列表后获取窗口,但这也同样有效。不过,我确实有一个问题,您有一个评论“那么它可能是一个更大的”。为什么是“可能”?您有多确定这将是正确的?
    • 在您的代码中,它应该始终是一个sizer。我想不出还有什么东西会从我的头顶返回 None ,但是那里有一些我不太熟悉的奇怪的小部件。我怀疑它会在 95% 左右的情况下起作用。
    【解决方案2】:

    你要走的路通向黑暗面!回头!

    你应该做类似的事情

    def __init__(self):
         ...
         self.widgets = {
           'text_input':textBox,
           'btn1':btn1,
           ....
    
         }
    

    然后稍后通过

    访问它们
     my_instance.widgets['text_input'].GetValue()
    

    或

    def validate(self):
          self.widgets['text_input'].GetValue()
    

    【讨论】:

    • 黑暗面?它有什么不好?如果我更改 GUI,则需要更新“轻量级”方法。此外,GetAllChildren 现在只返回一个空列表 :(
    • 是的,但是保留一个列表会更容易,因为它已经存在,而您必须按需生成另一个。
    • 您还知道您正在使用哪个文本字段或按钮...而不是仅仅知道它是一个小部件,然后您需要检查...的类型并且您需要在每个当你想做任何事情的时候......说迈克的回答非常好(通常)并回答了所问的问题,(即使我不赞成这种方法:P)(基本上最大的问题是复杂性迅速扩大控制,代码变得不可维护)
    猜你喜欢
    • 2012-12-10
    • 1970-01-01
    • 2011-07-06
    • 2013-10-07
    • 2020-08-26
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多