以下程序有内存泄漏(我在linux系统上用top
命令验证了这一点)
import wx
from random import randint
class MyPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent)
self._parent = parent
self._nb_buttons = 0
self._main_sizer = wx.BoxSizer(wx.VERTICAL)
self._ctrl_sizer = wx.BoxSizer(wx.HORIZONTAL)
self._btns_sizer = wx.BoxSizer(wx.VERTICAL)
self._btn_tim = wx.Button(self,label="Start auto")
self._btn_tim.Bind(wx.EVT_BUTTON, self.OnStartStopEvent)
self._ctrl_sizer.Add(self._btn_tim, 0, wx.CENTER|wx.ALL, 5 )
self._main_sizer.Add(self._ctrl_sizer, 0, wx.CENTER )
self._main_sizer.Add(self._btns_sizer, 0, wx.CENTER|wx.ALL,10)
self.SetSizer(self._main_sizer)
self._timer1 = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self._timer1)
self._timer_running = False
def OnStartStopEvent(self,event):
if self._timer_running: # toggle state of Timer
self._timer1.Stop()
self._btn_tim.SetLabel("Start")
self._timer_running = False
else:
self._timer1.Start(200,False)
self._btn_tim.SetLabel("Stop")
self._timer_running = True
def AddWidget(self):
self._nb_buttons += 1
label = "Button %d" % self._nb_buttons
name = "button%d" % self._nb_buttons
new_button = wx.Button(self,label=label, name=name)
self._btns_sizer.Add( new_button, 0, wx.ALL, 5 )
self._parent._my_sizer.Layout()
self._parent.Fit()
def RemoveWidget(self):
if self._btns_sizer.GetChildren():
self._btns_sizer.Hide(self._nb_buttons -1 )
self._btns_sizer.Remove(self._nb_buttons -1 )
self._nb_buttons -= 1
self._parent._my_sizer.Layout()
self._parent.Fit()
def OnTimer(self,event):
n = randint(-3,3)
if self._nb_buttons < 2: n += randint(0,2)
if self._nb_buttons > 10: n -= randint(0,3)
while n > 0:
self.AddWidget()
n -= 1
while n < 0:
self.RemoveWidget()
n += 1
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,parent=None, title="Add remove buttons")
self._my_sizer = wx.BoxSizer(wx.VERTICAL)
panel1 = MyPanel(self)
self._my_sizer.Add(panel1, 1, wx.EXPAND)
self.SetSizer(self._my_sizer)
self.Fit()
self.Show()
def main():
app = wx.App(False)
frame1 = MyFrame()
app.MainLoop()
if __name__ == '__main__':
main()
问题在于RemoveWidget
,该按钮已从Sizer
移除,但未从父wx.Panel
移除。
有哪些方法可以从父级wx.Button
移除wx.Panel
?
当我搜索&#34;删除wxPython小部件&#34;时,我发现的答案只告诉了如何从sizer中删除。 (事实上,我的代码是http://www.blog.pythonlibrary.org/2012/05/05/wxpython-adding-and-removing-widgets-dynamically/)的变体。
RemoveChild
类中有一个wx.Window
方法,但文档说它是内部的,不应该被用户代码调用(https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.RemoveChild)
答案 0 :(得分:2)
我想我明白了。我在Windows 10上,但我观察到相同的内存泄漏。将RemoveWidget方法修改为可在我的计算机上解决它。 有关说明,请参阅代码注释
编辑以反映RobinDunn的输入
def RemoveWidget(self):
if self._btns_sizer.GetChildren():
# GetItem returns a SizerItem, to get the actual button we have to call GetWindow
window = self._btns_sizer.GetItem(self._nb_buttons - 1).GetWindow()
# Calling Destroy removes widget from parent and sizer
window.Destroy()
self._nb_buttons -= 1
self._parent._my_sizer.Layout()
self._parent.Fit()