Reference to a Component to allow imperative modifications.
While Edifice is a declarative library and tries to abstract away the need to issue imperative commands to widgets, this is not always possible, either due to limitations with the underlying backened, or because some feature implemented by the backend is not yet supported by the declarative layer. In these cases, you might need to issue imperative commands to the underlying widgets and components, and References gives you a handle to the currently rendered Component.
Consider the following code:
class MyComp(Component): def __init__(self): self.ref = None def issue_command(self, e): self.ref.issue_command() def render(self): self.ref = AnotherComponent(on_click=self.issue_command) return self.ref
This code is incorrect since the component returned by render is not necessarily the Component rendered on Screen, since the old component (with all its state) will be reused when possible. The right way of solving the problem is via references:
class MyComp(Component): def __init__(self): self.ref = Reference() def issue_command(self, e): self.ref().issue_command() def render(self): return AnotherComponent(on_click=self.issue_command).register_ref(self.ref)
Under the hood, register_ref registers the Reference object to the component returned by the render function. While rendering, Edifice will examine all requested references and attaches them to the correct Component.
Initially, a Reference object will point to None. After the first render, they will point to the rendered Component. When the rendered component dismounts, the reference will once again point to None. You may assume that References are valid whenever they are not None. References evaluate false if the underlying value is None.
References can be dereferenced by calling them. An idiomatic way of using references is:
if ref: ref().do_something()
If you want to access the Qt widget underlying a base component, you can use the
underlyingattribute of the component:
class MyComp(Component): def __init__(self): self.ref = Reference() def did_render(self): if self.ref: self.ref().underlying.setText("Hi") def render(self): return Label("Hi").register_ref(self.ref)