nucleic / enaml

Declarative User Interfaces for Python
http://enaml.readthedocs.io/en/latest/
Other
1.53k stars 130 forks source link

RawWidget does not recive updates #437

Closed Tillsten closed 3 years ago

Tillsten commented 3 years ago

Here in the example below, the RawWidget does not register the changes to i.

from enaml.widgets.api import (MainWindow, Label, Container, Timer, RawWidget)
from enaml.core.api import Looper, Declarative, d_
from enaml.application import deferred_call

from atom.api import *
from enaml.qt import QtWidgets

class Model(Atom):
    i = Int()

    def update(self):
        self.i = self.i+1

class Test(RawWidget):
    __slots__ = ('___weakref___')

    i = d_(Int())

    def create_widget(self, parent):
        return QtWidgets.QWidget(parent=parent)

    @observe('i')
    def log(self, change):
        print(self.i)

enamldef Main(MainWindow):
    attr model = Model()    
    Test: raw:        
        i << model.i
    Label:
        text << str(model.i)
    func update():
        model.update()
    Timer: timer:
        interval = 200
        single_shot = False
        timeout :: deferred_call(update)
    activated ::
        timer.start()
Tillsten commented 3 years ago

Suprisingly I add an reference of i to widget itself it does work?

def create_widget(self, parent):
      wid = QtWidgets.QWidget(parent=parent)
      wid.i = self.i
      return wid
frmdstryr commented 3 years ago

enaml and atom are lazy (or should I say smart?). They don't do work that is unnecessary.

Since your Test widget is never using i the expression is never setup / observed. When you do self.i it then creates the observer.

Simply read i once and it works.


enamldef Main(MainWindow):
    attr model = Model()

    Test: raw:
        i << model.i
    Label:
        text << str(model.i)
    func update():
        model.update()
    Timer: timer:
        interval = 200
        single_shot = False
        timeout :: deferred_call(update)
    activated ::
        raw.i # Read i
        timer.start()
Tillsten commented 3 years ago

Thanks @frmdstryr, is there more documentation on this behavior? For a newbie like me it is absolutly not clear why it does not in the first place.

MatthieuDartiailh commented 3 years ago

I would have to check if it is documented but enaml does ignore creation events. However I need to ponder a bit more this specific example. I feel like after the first event it should work.

sccolbert commented 3 years ago

Change your Label to read the value from your Test widget instead of the model, and it will work. Frmdstryr is correct in that Enaml is as lazy as possible (it's a lazily evaluated dependency graph). If you never use the value, the expression won't be executed.

On Fri, Jan 29, 2021 at 9:49 AM Matthieu Dartiailh notifications@github.com wrote:

I would have to check if it is documented but enaml does ignore creation events. However I need to ponder a bit more this specific example. I feel like after the first event it should work.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nucleic/enaml/issues/437#issuecomment-769884593, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABBQSOVMEVQ7KMYXGQSCO3S4LKIDANCNFSM4WY7SGJQ .

Tillsten commented 3 years ago

My real usecase is a little bit more complicated, i am not sure if this kind of redirection is always useful. At least now I know how to work around that issue.

MatthieuDartiailh commented 3 years ago

Closing feel free to reopen if needed.

Tillsten commented 3 years ago

I still think this should be at least advertised in the docs somewhere, since the behavior is not intuitive.