Das folgende Programm hat einen Speicherverlust (I bestätigte diese auf einem Linux-System, mit dem top
Befehl)Entfernen ein Widget von seiner WxPython Mutter
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()
Das Problem ist, dass in RemoveWidget
, wird der Knopf entfernt von die Sizer
, aber nicht von der übergeordneten wx.Panel
.
Wie entferne ich die wx.Button
vom übergeordneten (wx.Panel
in diesem Fall)?
Als ich nach "remove wxPython widget" suchte, sagten die Antworten, die ich fand, nur, wie man von Sizer entfernt. (In der Tat ist mein Code eine Variation von http://www.blog.pythonlibrary.org/2012/05/05/wxpython-adding-and-removing-widgets-dynamically/).
Es gibt eine RemoveChild
Methode in der wx.Window
Klasse, aber Dokumentation sagt, es interne und sollte nicht durch Benutzercode (https://wxpython.org/Phoenix/docs/html/wx.Window.html#wx.Window.RemoveChild)
Widgets werden sich aus den Sizer entfernen, wenn sie zerstört werden, also ja, es ist überflüssig. Außerdem entfernen sich Widgets selbst aus der Child-Liste der Eltern, so dass der Aufruf von 'RemoveChild' ebenfalls redundant ist. IOW, der Aufruf von 'window.Destroy()' wird ausreichen, um das Widget und seine Ressourcen zu entfernen und die notwendigen Bereinigungen im Parent und im Sizer durchzuführen. – RobinDunn
Überprüft Ihren Code in Linux (Raspbian): kein Speicherleck entweder. –