wxpython window 在事件处理后崩溃

wxpython window crashes after event handling

此代码读取图片并将其作为背景放在 window 中。 有两个问题我无法解释:

为什么会这样? 谢谢

import wx
import wx.lib.buttons as buttons

class Main(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, id=-1, title=title, size=(300, 300))
        self.initUI()
        self.panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, size=(10000, 10000))
        self.backGroundImage=''
        self.Layout()

    def initUI(self):
        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        fileMenu.AppendSeparator()

        imp = wx.Menu()
        importBackgroundButton = imp.Append(wx.ID_ANY, 'Import background')
        self.Bind(wx.EVT_MENU, self.OnImportBackground, importBackgroundButton)
        fileMenu.AppendMenu(wx.ID_ANY, 'I&mport', imp)
        menubar.Append(fileMenu, '&File')
        self.SetMenuBar(menubar)
        self.SetTitle('test')
        self.Centre()
        self.Show(True)

    #load background
    def OnImportBackground(self, e):
        app = wx.App(None)
        style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
        dialog = wx.FileDialog(None, 'Open', wildcard='*.png', style=style)
        if dialog.ShowModal() == wx.ID_OK:
            path = dialog.GetPath()
        else:
            path = None
        dialog.Destroy()
        self.backgroundImage = ButtonImage(self, self.panel, path, (0, 0))
        W = self.backgroundImage.bmp.GetSize()[0]
        H = self.backgroundImage.bmp.GetSize()[1]
        self.SetSize((W+16, H+58))
        self.Refresh()
        #crash


class ButtonImage():
    def __init__(self, parent, panel, nameImage, pos):
        self.panel = panel
        self.bmp = wx.Bitmap(nameImage, wx.BITMAP_TYPE_ANY)
        self.maxPiecePositionX = self.panel.GetSize()[0] - self.bmp.GetSize()[0]
        self.maxPiecePositionY = self.panel.GetSize()[1] - self.bmp.GetSize()[1]
        self.bmapBtn = wx.BitmapButton(self.panel, id=wx.ID_ANY, bitmap=self.bmp, style=wx.NO_BORDER, pos=pos)
        self.bmapBtn.Bind(wx.EVT_LEFT_DOWN, self.OnClickDown, self.bmapBtn)
        self.bmapBtn.Bind(wx.EVT_LEFT_UP, self.OnClickUp, self.bmapBtn)
        self.bmapBtn.Bind(wx.EVT_MOTION, self.MoveButton, self.bmapBtn)
        self.hold = 0
        self.holdPosition = (0, 0)

    def EnterButton(self, event):
        pass

    def LeaveButton(self, event):
        self.hold = 0

    def OnClickDown(self, event):
        obj = event.GetEventObject()
        self.hold = 1
        self.holdPosition = (event.GetX(), event.GetY())

    def OnClickUp(self, event):
        self.hold = 0

    def MoveButton(self, event):
        deltaX, deltaY = 0, 0
        if self.hold:
            deltaX = event.GetPosition()[0] - self.holdPosition[0]
            deltaY = event.GetPosition()[1] - self.holdPosition[1]
            newPositionX = self.bmapBtn.GetPosition()[0] + deltaX
            newPositionY = self.bmapBtn.GetPosition()[1] + deltaY
            if (0 < newPositionX < self.maxPiecePositionX) and (0 < newPositionY < self.maxPiecePositionY):
                self.bmapBtn.SetPosition((newPositionX, newPositionY))
            else:
                self.holdPosition = self.holdPosition[0] + deltaX, self.holdPosition[1] + deltaY
            self.bmapBtn.Raise()
            self.bmapBtn.Refresh()

app = wx.App()
frame = Main(None, "Test")
frame.Show()
app.MainLoop()

这个例子问题太多,要花很长时间来解释。例如,你创建了一个新的 ButtonImage,它本质上是一个 wx.BitmapButton,每次你调用 OnImportBackground 而没有破坏旧的,堆叠了一组没有正确布局的位图按钮他们。

但是,每次调用 OnImportBackground 时,您都会实例化一个新的 wx.App,这是什么把钉子钉进了棺材里。如果去掉这条线(完全没有意义),框架至少可以关闭。

但是要看到 "the right way (TM)" 做到这一点,请看 this Whosebug post