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

时间:2012-04-20 13:54:32

标签: python loops widget wxpython wxwidgets

我正在教自己(Wx)Python而且卡住了。我想创建一个子窗口,它在我的TestFrame中有一组重复的信息,其中包含我的大部分代码。问题是,它只在我的代码中显示一个小部件。我试图弄清楚以下内容,对我来说很重要。

**请注意,此代码是this页面的扩展名。*

  1. 如何让“AddBox”类中的多个小部件正确显示?
  2. 当我的窗口调整大小时,它会破坏按钮图像,就像连接的屏幕一样。我怎么能解决这个问题?
  3. 如何调用/绑定这些动态创建的小部件?
  4. Bonus:这里需要“OnSize”模块吗?
  5. 感谢您的帮助。如果你允许/适当的话,我愿意通过Paypal向你赢得5美元的奖金。

    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()
    

2 个答案:

答案 0 :(得分:1)

这里的代码非常复杂,难以理解。你几乎不需要使用wx.Window。事实上,在使用wxPython的近6年中,我从未直接使用它。 PySimpleApp也已弃用。无论如何,我清理了一堆代码并在下面重新做了。我不确定这是不是你要找的东西。另请注意,我将ScrolledWindow替换为ScrolledPanel,因为我认为后者更容易使用:

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()

您还应该查看窗口小部件检查工具。它可以帮助您找出这样的布局问题:http://wiki.wxpython.org/Widget%20Inspection%20Tool

编辑:我认为上面的代码处理了第1和第2项。对于#3,请参阅我去年写的以下文章:http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/

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

答案 1 :(得分:0)

我现在只回答3:为每个动态创建的小部件分配一个ID,将此ID存储在字典中({id:widget})并将回调函数作为lambda函数传递或使用functools.partial将ID传递给“真正的”回调。 (当然你可以直接在lambda函数上传递小部件,但是我喜欢在某个地方创建小部件的实例,如果我需要在某个时候访问它们的话)

    def __init__(...):
    self.event_dispatch = dict()

    ...

    for id in xrange(500, 508):
        wind = AddBox(self.scrolling_window, id)
        ...
        self.event_dispatch[id] = wind
        self.scrolling_window.Bind(wx.MY_EVENT, lambda evt: self.on_event(evt, id), id=id)


def on_event(event, id):
    widget = self.event_dispatch[id]
    # do something with widget