Package: pyedifice
EdificeDeclarative GUI framework for Python and QtEdifice is a Python library for building declarative application user interfaces.ModerndeclarativeUI paradigm from web development.100% Pythonapplication development, no language inter-op.Anativedesktop app instead of a bundled web browser.Fast iteration viahot-reloading.This modern declarative UI paradigm is also known as
“The Elm Architecture,”
or “Model-View-Update.”Edifice usesPySide6orPyQt6as a backend. So Edifice is likeReact, but with
Python instead of JavaScript, andQt Widgetsinstead of the HTML DOM.If you have React experience, you'll find Edifice to be very easy to pick up.
Edifice has function props and Hooks just like React.Getting StartedInstallationpip install PySide6pip install pyedificeSourcepublished atgithub.com/pyedifice/pyedificePackagepublished atpypi.org/project/pyedificeDocumentationpublished atpyedifice.github.ioWhy Edifice?DeclarativeThe premise of Edifice is that
GUI designers should only need to worry aboutwhatis rendered on the screen,
nothowthe content is rendered.Most existing GUI libraries in Python, such as Tkinter and Qt, operate imperatively.
To create a dynamic application using these libraries,
you must not only think aboutwhatto display to the user given state changes,
but alsohowto issue the commands to achieve the desired display.Edifice allows you to declarewhatshould be rendered given the current state,
leaving thehowto the library.User interactions update the state, and state changes update the GUI.
You only need to specify what is to be displayed given the current state and how
user interactions modify this state.With Edifice you write code like:number,set_number=use_state(0)withView():Button("Add 5",on_click=lambdaevent:set_number(number+5))Label(str(number))and get the expected result: the GUI always displays
a button and a label displaying the current value ofnumber.
Clicking the button adds 5 to thenumber,
and Edifice will handle updating the GUI.Edifice vs. QMLQMLis Qt’s declarative GUI framework for Qt. Edifice differs from QML in these aspects:Edifice programs are written purely in Python, whereas QML programs are written
in Python + a special QML language + JavaScript.Because Edifice interfaces are built in Python code, binding the code to the declared UI is much more
straightforward.Edifice makes it easy to create dynamic applications. It's easy to create, shuffle, and destroy widgets
because the interface is written in Python code. QML assumes a much more static interface.By analogy, QML is like HTML + JavaScript, whereas Edifice is like React.js.
While QML and HTML are both declarative UI frameworks,
they require imperative logic to add dynamism.
Edifice and React allow fully dynamic applications to be specified declaratively.How it worksAn Edifice component declares the mapping from the state to UI.
The state of a component is divided intopropsandstate.propsare passed to the component in the constructor,
whereasstateis the component’s own internal state.Changes topropsorstatewill trigger a re-render of the component
and all its children.
The old and new component trees will be compared to one another,
and a diffing algorithm will determine which components previously existed and which ones are new
(the algorithm behaves similarly to the React diffing algorithm).
Components that previously existed will maintain theirstate, whereas theirpropswill be updated.
Finally, Edifice will try to ensure that the minimal update commands are issued to the UI.
All this logic is handled by the library, and the components need not care about it.Development ToolsDynamic hot-reloadDyanamic hot-reload is very useful for fine-tuning the presentation styles
of Elements deep within your application.
You can test if the margin should be10pxor15pxinstantly without closing the app, reopening it, and waiting for everything to load.To run your application with dynamic hot-reload, run:python -m edifice path/to/app.py MyRootElementThis will runapp.pywithMyRootElementmounted as the root.
A separate thread will listen to changes in all Python files in the directory containingapp.py(recursing into subdirectories).
You can customize which directory to listen to using the--dirflag.When a file in your application is changed, the loader will reload all components in that file
with preserved props (since that state comes from the caller), reset state,
and trigger a re-render in the main thread.Because rendering is abstracted away, it is simple to diff the UI trees and have
the Edifice renderer figure out what to do using its normal logic.Element InspectorSimilar to the Inspect Elements tool of a browser, the Element inspector will show you all Elements in your application along with the props and state, allowing you to examine the internal state of your complex component without writing a million print statements.
Since the UI is specified as a (pure) function of state, the state you see completely describes your application,
and you can even do things like rewinding to a previous state.set_trace()PDB does not work well with PyQt applications.edifice.set_trace()is
equivalent topdb.set_trace(),
but it can properly pause the PyQt event loop
to enable use of the debugger
(users of PySide need not worry about this).LicenseEdifice isMIT Licensed.Edifice uses Qt under the hood, and both PyQt6 and PySide6 are supported. Note that PyQt6 is distributed with theGPLlicense while PySide6 is distributed
under the more flexibleLGPLlicense.
SeePyQt vs PySide Licensing.Version History / Change Log / Release NotesSeeRelease Notes(source:versions.rst)ContributionContributions are welcome; please send Pull Requests! SeeDEVELOPMENT.mdfor development notes.When submitting a Pull Request, think about adding tests totestsand
adding a line to theUnreleasedsection of the
change logversions.rst.Poetry Build SystemThe Poetrypyproject.tomlspecifies the package dependecies.Because Edifice supports PySide6 and PyQt6 at the same time, neither
are required by[tool.poetry.dependencies]. Instead they are both
optional[tool.poetry.group.dev.dependencies]. A project which depends
on Edifice should also depend on either PySide6 or PyQt6.Therequirements.txtis generated bypoetry export -f requirements.txt --output requirements.txtTo use the latest Edifice with a Poetrypyproject.tomlfrom Github
instead of PyPI, seePoetry git dependencies,
for example:[tool.poetry.dependencies]
python = ">=3.10,<3.11"
pyedifice = {git = "https://github.com/pyedifice/pyedifice.git"}
pyside6 = "6.5.1.1"