flexx icon indicating copy to clipboard operation
flexx copied to clipboard

PyWidget quietly gets cleaned up if it is not referenced

Open matkuki opened this issue 4 years ago • 1 comments

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.

matkuki avatar Jul 26 '19 11:07 matkuki

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 :)

almarklein avatar Aug 01 '19 10:08 almarklein