WxPython:子窗口中的多个小部件

WxPython:子窗口中的多个小部件,python,loops,widget,wxpython,wxwidgets,Python,Loops,Widget,Wxpython,Wxwidgets,我正在自学(Wx)Python,却被卡住了。我想创建一个子窗口,它在我的TestFrame中包含一组重复出现的信息,TestFrame包含了我的大部分代码。问题是,它在我的代码中只显示了一个小部件。我正试着按照对我的重要性,找出以下几点 **请注意,此代码是对页面的扩展* 如何允许“AddBox”类中的多个小部件正确显示 当我的窗口被调整大小时,它会破坏按钮图像,如所附屏幕中所示。我怎样才能解决这个问题 如何调用/绑定这些动态创建的小部件 奖励:这里需要“OnSize”模块吗 谢谢你的帮助。如果

我正在自学(Wx)Python,却被卡住了。我想创建一个子窗口,它在我的TestFrame中包含一组重复出现的信息,TestFrame包含了我的大部分代码。问题是,它在我的代码中只显示了一个小部件。我正试着按照对我的重要性,找出以下几点

**请注意,此代码是对页面的扩展*

  • 如何允许“AddBox”类中的多个小部件正确显示
  • 当我的窗口被调整大小时,它会破坏按钮图像,如所附屏幕中所示。我怎样才能解决这个问题
  • 如何调用/绑定这些动态创建的小部件
  • 奖励:这里需要“OnSize”模块吗
  • 谢谢你的帮助。如果允许/适当,我愿意通过Paypal向赢家捐款5美元,如果你PM我

    import wx
    
    class AddBox(wx.Window):
        def __init__(self, parent):
            wx.Window.__init__(self, parent)        
    
            pbox = wx.BoxSizer(wx.VERTICAL)
    
            controlback = wx.Button(self, label="Back")
            controlforward = wx.Button(self, label="Forward")
    
            pbox.AddMany([(controlback, 1, wx.ALL), (controlforward, 1, wx.ALL)])
    
    class TestFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, -1, size=(1000, 550))
    
            self.Bind(wx.EVT_SIZE, self.OnSize)
    
            pbox0 = wx.BoxSizer(wx.VERTICAL)
            controlback0 = wx.Button(self, label="Back0")
            controlforward0 = wx.Button(self, label="Forward0")
            pbox0.AddMany([(controlback0, 1, wx.ALL), (controlforward0, 1, wx.ALL)])
            pbox2 = wx.BoxSizer(wx.VERTICAL)
    
            self.scrolling_window = wx.ScrolledWindow( self )
            self.scrolling_window.SetScrollRate(1,6)
            self.scrolling_window.EnableScrolling(True,True)
            self.sizer_container = wx.BoxSizer( wx.VERTICAL )
            self.sizer = wx.BoxSizer( wx.VERTICAL )
            self.sizer_container.Add(self.sizer,1,wx.CENTER,wx.EXPAND)
            self.child_windows = []
            for i in range(0,8):
                wind = AddBox(self.scrolling_window)
                self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
                self.child_windows.append(wind)
    
            self.scrolling_window.SetSizer(self.sizer_container)
            #self.Layout() #not needed?
    
    
            pbox2.AddMany([(self.sizer_container, 1, wx.ALL)])
    
        def OnSize(self, event):
            self.scrolling_window.SetSize(self.GetClientSize())
    
    if __name__=='__main__':
        app = wx.PySimpleApp()
        f = TestFrame()
        f.Show()
        app.MainLoop()
    

    这里的代码非常复杂,很难理解。您几乎不需要使用wx.Window。事实上,在使用wxPython近6年的时间里,我从未直接使用过它。PySimpleApp也不推荐使用。无论如何,我清理了一堆代码,然后在下面重新做了。我不确定这是否是你想要的。还请注意,我将out Scrolled Window替换为Scrolled Panel,因为我认为后者更易于使用:

    import wx
    import  wx.lib.scrolledpanel as scrolled
    
    class TestFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, size=(1000, 550))
            panel = wx.Panel(self)
    
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            pbox0 = wx.BoxSizer(wx.VERTICAL)
            controlback0 = wx.Button(panel, label="Back0")
            controlforward0 = wx.Button(panel, label="Forward0")
            pbox0.Add(controlback0, 0, wx.ALL)
            pbox0.Add(controlforward0, 0, wx.ALL)
            mainSizer.Add(pbox0)
    
            self.scrolling_window = scrolled.ScrolledPanel( panel )
            self.scrolling_window.SetAutoLayout(1)
            self.scrolling_window.SetupScrolling()
            self.sizer = wx.BoxSizer( wx.VERTICAL )
            self.child_windows = []
            for i in range(0,8):
                wind = self.addBox()
                self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
            self.scrolling_window.SetSizer(self.sizer)
    
            mainSizer.Add(self.scrolling_window, 1, wx.EXPAND)
            panel.SetSizer(mainSizer)
    
        def addBox(self):
            pbox = wx.BoxSizer(wx.VERTICAL)
    
            controlback = wx.Button(self.scrolling_window, label="Back")
            controlforward = wx.Button(self.scrolling_window, label="Forward")
    
            pbox.AddMany([(controlback, 0, wx.ALL), (controlforward, 0, wx.ALL)])
            return pbox
    
        def OnSize(self, event):
            self.scrolling_window.SetSize(self.GetClientSize())
    
    if __name__=='__main__':
        app = wx.App(False)
        f = TestFrame()
        f.Show()
        app.MainLoop()
    
    您还应该看看小部件检查工具。它将帮助您解决如下布局问题:

    编辑:我认为上面的代码处理了第1项和第2项。关于#3,请参阅我去年写的以下文章:


    基本上,您可以在循环本身中绑定,然后在事件处理程序中,使用event.GetEventObject()返回调用的小部件并设置其值或其他内容。至于你的第四个问题,我会说不,你不需要OnSize方法。在wxPython中几乎不需要重写它,在我的示例代码中我当然不需要重写它。

    这里的代码非常复杂,很难理解。您几乎不需要使用wx.Window。事实上,在使用wxPython近6年的时间里,我从未直接使用过它。PySimpleApp也不推荐使用。无论如何,我清理了一堆代码,然后在下面重新做了。我不确定这是否是你想要的。还请注意,我将out Scrolled Window替换为Scrolled Panel,因为我认为后者更易于使用:

    import wx
    import  wx.lib.scrolledpanel as scrolled
    
    class TestFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, size=(1000, 550))
            panel = wx.Panel(self)
    
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            pbox0 = wx.BoxSizer(wx.VERTICAL)
            controlback0 = wx.Button(panel, label="Back0")
            controlforward0 = wx.Button(panel, label="Forward0")
            pbox0.Add(controlback0, 0, wx.ALL)
            pbox0.Add(controlforward0, 0, wx.ALL)
            mainSizer.Add(pbox0)
    
            self.scrolling_window = scrolled.ScrolledPanel( panel )
            self.scrolling_window.SetAutoLayout(1)
            self.scrolling_window.SetupScrolling()
            self.sizer = wx.BoxSizer( wx.VERTICAL )
            self.child_windows = []
            for i in range(0,8):
                wind = self.addBox()
                self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
            self.scrolling_window.SetSizer(self.sizer)
    
            mainSizer.Add(self.scrolling_window, 1, wx.EXPAND)
            panel.SetSizer(mainSizer)
    
        def addBox(self):
            pbox = wx.BoxSizer(wx.VERTICAL)
    
            controlback = wx.Button(self.scrolling_window, label="Back")
            controlforward = wx.Button(self.scrolling_window, label="Forward")
    
            pbox.AddMany([(controlback, 0, wx.ALL), (controlforward, 0, wx.ALL)])
            return pbox
    
        def OnSize(self, event):
            self.scrolling_window.SetSize(self.GetClientSize())
    
    if __name__=='__main__':
        app = wx.App(False)
        f = TestFrame()
        f.Show()
        app.MainLoop()
    
    您还应该看看小部件检查工具。它将帮助您解决如下布局问题:

    编辑:我认为上面的代码处理了第1项和第2项。关于#3,请参阅我去年写的以下文章:


    基本上,您可以在循环本身中绑定,然后在事件处理程序中,使用event.GetEventObject()返回调用的小部件并设置其值或其他内容。至于你的第四个问题,我会说不,你不需要OnSize方法。在wxPython中几乎不需要重写它,在我的示例代码中我当然不需要重写它。

    我现在只需要回答3:为每个动态创建的小部件分配一个ID,将该ID存储在字典({ID:widget})中,并将lambda函数作为回调函数传递,或者使用functools.partial将ID传递给“真实”回调。(当然,您可以通过lambda函数直接传递小部件,但是如果我需要访问这些小部件,我希望在某个地方有创建的小部件的实例)


    现在我只有一个关于3的答案:为每个动态创建的小部件分配一个ID,将该ID存储在字典({ID:widget})中,并将lambda函数作为回调函数传递,或者使用functools.partial将ID传递给“real”回调。(当然,您可以通过lambda函数直接传递小部件,但是如果我需要访问这些小部件,我希望在某个地方有创建的小部件的实例)


    到现在为止,一直都还不错。。。但是,当Mike Driscoll的代码中存在事件时,这种方法可以很好地工作,但它不是从“由外而内”进行的。也就是说,我不确定如何从controlback0访问位于“for循环”中的textctrl。(谢谢你的帮助)到目前为止很好。。。但是,当Mike Driscoll的代码中存在事件时,这种方法可以很好地工作,但它不是从“由外而内”进行的。也就是说,我不确定如何从controlback0访问位于“for循环”中的textctrl。(感谢您的帮助)在正确的轨道上-这是有帮助的,但它没有显示如何从外到内进行编辑。例如,如果按下controlback或controlback0,如何在addBox模块中编辑textctrl?我这里肯定缺少一些内容。在您的示例中,哪里有TextCtrl?没有。为什么按随机按钮可以编辑文本控件?如果您想按一个按钮打开编辑,那么您需要保留按钮的某种数据结构(可能是字典)以及它们映射到的文本控件。然后当按下按钮时,它将启用文本控件并将焦点放在那里。谢谢。我在Q1上度过了最艰难的时光,你优雅地修复了它。感谢您向我展示了如何使用wx.Window,我不确定如何实现这一点,您给了我开始理解这里发生了什么所需要的动力。至于第三季度,你的回答也很有帮助,使我能够自动填充多个textctrl。总有一天我会像这样把人们赶走。。。非常感谢。在正确的轨道上-这是有帮助的,但它没有显示如何从外到内进行编辑。例如,如果按下controlback或controlback0,如何在addBox模块中编辑textctrl?我这里肯定缺少一些内容。在您的示例中,哪里有TextCtrl?没有。为什么按随机按钮可以编辑文本控件?如果您想按一个按钮打开编辑,那么您需要保留按钮的某种数据结构(可能是字典)以及它们映射到的文本控件。然后当按下按钮时,它将启用文本控件并将焦点放在那里。谢谢。我正在吃晚饭