从wxPython父级

时间:2016-12-09 04:49:02

标签: python wxpython

以下程序有内存泄漏(我在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

1 个答案:

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