1

我正在自学(Wx)Python并被卡住了。我想创建一个子窗口,它在我的 TestFrame 中包含一组重复出现的信息,其中包含我的大部分代码。问题是,它只在我的代码中显示一个小部件。我正在尝试按照对我来说重要的顺序来弄清楚以下内容。

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

  1. 如何允许“AddBox”类中的多个小部件正确显示?
  2. 当我的窗口被调整大小时,它会破坏按钮图像,就像附加的屏幕一样。我该如何解决这个问题?
  3. 你如何调用/绑定这些动态创建的小部件?
  4. 奖励:这里需要“OnSize”模块吗?

感谢您的帮助。如果允许/适当,如果您 PM 我,我愿意通过 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()
4

2 回答 2

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 -多个小部件到相同的处理程序/

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

于 2012-04-20T14:35:37.107 回答
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
于 2012-04-20T14:38:19.227 回答