flexx
flexx copied to clipboard
PyWidget quietly gets cleaned up if it is not referenced
I found that this code prints CLICK:
from flexx import flx, ui, event, config
class MyWidget(flx.PyWidget):
def init(self):
super().init()
with flx.StackLayout() as self.layout:
self.but = flx.Button(text="BUTTON")
self.layout.set_current(self.but)
@flx.action
def add_sub_widget(self):
with self.layout:
self.sub = MySubWidget()
self.layout.set_current(self.sub._jswidget)
@flx.reaction('but.pointer_click')
def click(self, *events):
self.add_sub_widget()
class MySubWidget(flx.PyWidget):
def init(self):
super().init()
with flx.PinboardLayout():
self.sub_but = flx.Button(text="SUB BUTTON")
@flx.reaction('sub_but.pointer_click')
def click(self, *events):
print("CLICK")
m = flx.launch(MyWidget)
flx.run()
... while this one doesn't:
from flexx import flx, ui, event, config
class MyWidget(flx.PyWidget):
def init(self):
super().init()
with flx.StackLayout() as self.layout:
self.but = flx.Button(text="BUTTON")
self.layout.set_current(self.but)
@flx.action
def add_sub_widget(self):
with self.layout:
sub = MySubWidget() # <-- DIFFERENT FROM ABOVE
self.layout.set_current(sub._jswidget) # <-- DIFFERENT FROM ABOVE
@flx.reaction('but.pointer_click')
def click(self, *events):
self.add_sub_widget()
class MySubWidget(flx.PyWidget):
def init(self):
super().init()
with flx.PinboardLayout():
self.sub_but = flx.Button(text="SUB BUTTON")
@flx.reaction('sub_but.pointer_click')
def click(self, *events):
print("CLICK")
m = flx.launch(MyWidget)
flx.run()
Is this know? Could there be a warning emitted when something like this happens? It took me some time to find out where the problem was, it would be nice if there was a hint saying that the reactions will be ignored.
Oh, this is an interesting one. Since the PyWidget is not stored anywhere, it's cleaned up. In "normal" GUI toolkits the object would stay to exist because it's in the list of children of its parent, but because of the way that the PyWidget works (wrapping a JsWidget), this does not happen ...
To be honest, I am not sure what the best solution would be. My first inclination is that the component should somehow be bound to its _jswidget
, but this also feels hacky ...
Leaving this open for now. Until we actually fix this, make sure you keep a reference to your PyWidgets :)