@@ -35,7 +35,9 @@ First, install Qt and Edifice.
3535
3636
3737Let’s create the basic skeleton of our UI.
38- Copy this code into a new file, for example tutorial.py::
38+ Copy this code into a new file, :code: `tutorial.py `
39+
40+ .. code-block :: python
3941
4042 from edifice import App, Label, TextInput, HBoxView, Window, component
4143
@@ -50,6 +52,12 @@ Copy this code into a new file, for example tutorial.py::
5052 if __name__ == " __main__" :
5153 App(MyApp()).start()
5254
55+ Run this code with
56+
57+ .. code-block :: shell
58+
59+ python tutorial.py
60+
5361 What does this code do?
5462First we define a function :code: `MyApp ` which is decorated by
5563:func: `@component<component> `.
@@ -62,7 +70,7 @@ then declare its children, we use a
6270`with statement <https://docs.python.org/3/reference/compound_stmts.html#with >`_
6371context. Elements inside the :code: `with ` context are children.
6472
65- In HTML or XML, we might have written it as:
73+ In HTML or XML or React JSX , we might have written it as:
6674
6775.. code-block :: xml
6876
@@ -81,25 +89,13 @@ It takes the description of each Element, and it decides when and how to render
8189It does so by monitoring the **state ** of each Element, and it will re-render
8290when the Element **state ** changes.
8391
84- As you might expect, you can run this application with :code: `python tutorial.py `.
85- However, let us take advantage of Edifice's :doc: `dynamic loading capability<developer_tools> `,
86- so that we do not have to continually close the app and re-issue the command every time we change something.
87- To run the app with dynamic loading, first install watchdog::
88-
89- pip install watchdog
90-
91- then do::
92-
93- python -m edifice tutorial.py MyApp
94-
95- You should see a basic form emerge. However, it's not pretty, and it doesn't really do anything.
96-
9792We can change the formatting of the :class: `Label<Label> `, :class: `TextInput<edifice.TextInput> `, and
9893:class: `HBoxView<edifice.HBoxView> ` using Qt :doc: `styling<styling> `,
9994which is similar to CSS styling.
10095Here, we want to add padding between the HBoxView and Window boundary,
10196make the Labels shorter, and add a margin between the Label and TextInput.
102- For example::
97+
98+ .. code-block :: python
10399
104100 from edifice import App, Label, TextInput, HBoxView, Window, component
105101
@@ -119,14 +115,12 @@ For example::
119115 if __name__ == " __main__" :
120116 App(MyApp()).start()
121117
122- When we are running :code: `MyApp ` with dynamic loading, Edifice will detect the change
123- to the source file and reload :code: `MyApp ` at runtime so that we can see the styling
124- changes immediately.
125-
126118 Our application still doesn't do anything, however. Let's add an :code: `on_change `
127119event handler **prop ** for the :class: `TextInput<edifice.TextInput> `.
128120the :code: `on_change ` **prop ** function will be called whenever the contents in the
129- text input changes due to user action::
121+ text input changes due to user action.
122+
123+ .. code-block :: python
130124
131125 from edifice import App, Label, TextInput, HBoxView, Window, component, use_state
132126
@@ -146,7 +140,7 @@ text input changes due to user action::
146140 Label(" Measurement in meters:" , style = meters_label_style)
147141 TextInput(meters, style = input_style, on_change = meters_set)
148142 try :
149- feet = "%.3f" % ( float(meters) * METERS_TO_FEET)
143+ feet = f " { float (meters) * METERS_TO_FEET :.3f } "
150144 Label(f " Measurement in feet: { feet} " , style = feet_label_style)
151145 except ValueError : # Could not convert string to float
152146 pass # So don't render the Label
@@ -168,19 +162,13 @@ the :code:`on_change` **prop** for the :class:`TextInput<edifice.TextInput>`.
168162Whenever the user types in the text input, the state will be set and
169163the UI will re-render.
170164
171- Think of the component function as a map from the
165+ Think of the :func: ` @ component <component> ` function as a map from the
172166:code: `meters ` **state ** to an Element tree.
173167
174- In the component function, we read the value of :code: `meters ` and convert it to feet,
168+ In the :func: `@component <component> ` function, we read the value of :code: `meters `
169+ and convert it to feet,
175170and we render the text input and label Elements.
176171
177- If we want to see the **state ** changes in action, we can open the Element Inspector::
178-
179- python -m edifice --inspect tutorial.py MyApp
180-
181- The Element Inspector allows us to see the current **state ** and **props ** for all Elements in a UI.
182- Play around with the application and see how the **state ** changes.
183-
184172Now we want to add conversion from feet to meters. Instead of copying our code and repeating
185173it for each measurement pair, we can factor out the conversion logic into its own component.
186174We pass the conversion parameters into the component as **props ** arguments::
@@ -190,7 +178,7 @@ We pass the conversion parameters into the component as **props** arguments::
190178 METERS_TO_FEET = 3.28084
191179
192180 @component
193- def ConversionWidget(self, from_unit, to_unit, factor):
181+ def ConversionWidget(self, from_unit:str , to_unit:str , factor:float ):
194182
195183 current_text, current_text_set = use_state("0.0")
196184
@@ -202,7 +190,7 @@ We pass the conversion parameters into the component as **props** arguments::
202190 Label(f"Measurement in {from_unit}:", style=from_label_style)
203191 TextInput(current_text, style=input_style, on_change=current_text_set)
204192 try:
205- to_text = "%.3f" % ( float(current_text) * factor)
193+ to_text = f"{ float(current_text) * factor :.3f}"
206194 Label(f"Measurement in {to_unit}: {to_text}", style=to_label_style)
207195 except ValueError: # Could not convert string to float
208196 pass # So don't render the Label
@@ -216,3 +204,26 @@ We pass the conversion parameters into the component as **props** arguments::
216204
217205 if __name__ == "__main__":
218206 App(MyApp()).start()
207+
208+
209+ We can use the :doc: `Edifice Runner <developer_tools >` to run our application.
210+
211+ First install :code: `watchdog `.
212+
213+ .. code-block :: shell
214+
215+ pip install watchdog
216+
217+ Then run the application with the :doc: `Edifice Runner <developer_tools >`.
218+ This will run our application with **Element Inspector ** and **Hot-Reload **.
219+
220+ .. code-block :: shell
221+
222+ python -m edifice --inspect tutorial.py MyApp
223+
224+ The Element Inspector allows us to see the current **state ** and **props ** for all Elements in a UI.
225+ Type in the :class: `TextInput ` widget and see how the **state ** changes.
226+
227+ Editing and saving the :code: `ConversionWidget ` component source code will automatically
228+ reload the component and update the UI. (Editing the :code: `MyApp ` component will
229+ not reload the UI, because Hot-Reload does not work for the root component.)
0 commit comments