What is PUI
PUI is a reactive/declarative UI framework with two-way data binding. PUI doesn't do UI itself, it turns imperative UI libraries into reactive/declarative flavor with virtual DOM and aims to maintain interoperability.
CPPUI: Experimental C++ Version
Features
Installation
pip install QPUIQ
# Optional, for hot-reload
pip install jurigged
# Optional, for PySide6 backend
pip install PySide6
# Optional, for textual backend
pip install textual
# Optional, for wxPython backend
pip install wxPython
# Optional, for flet backend
pip install flet
Get Started
Hello World
# example/hello_world.py
from PUI.PySide6 import *
@PUIApp
def Example():
with Window(title="test", size=(320,240)):
Label("Hello world")
root = Example()
root.run()
State & Data Binding
# example/generic_textfield.py
from PUI.PySide6 import *
data = State()
class Example(Application):
def __init__(self):
super().__init__()
data.var = 0
def content(self):
with Window(title="blah"):
with VBox():
with HBox():
Button("-").click(self.on_minus)
Label(f"{data.var}")
Button("+").click(self.on_plus)
TextField(data("var")) # binding
def on_minus(self):
data.var -= 1
def on_plus(self):
data.var += 1
root = Example()
root.run()
View Component
# example/bleak_list.py
....
@PUI # View Component
def DeviceView(device, advertising_data):
Label(f"{device.address} {device.name} {advertising_data.rssi}")
class GUI(Application):
def __init__(self, state):
super().__init__()
self.state = state
def content(self):
with Window(title="BLE List"):
with VBox():
Label(f"Found {len(self.state.scanned_devices)} devices")
for device, advertising_data in self.state.scanned_devices:
DeviceView(device, advertising_data)
....
Layout & Styling
# example/pyside6_feedparser.py
...
with VBox():
Label(title).qt(StyleSheet={"font-weight":"bold"}) # QT-specific
with HBox():
with Scroll():
with VBox():
for i,e in enumerate(entries):
Label(e.title).click(self.entry_selected, i)
Spacer()
with Scroll().layout(weight=1): # Generic Layout Parameter
if 0 <= selected and selected < len(entries):
(Text(entries[selected].description)
.layout(padding=10) # Generic Layout Parameter
.qt(StyleSheet={"background-color":"white", "color":"black"})) # QT-specific
...
Canvas
# example/generic_canvas.py
from PUI.PySide6 import *
data = State()
class Example(Application):
def __init__(self):
super().__init__()
data.var = 50
def content(self):
with Window(title="blah", size=(640,480)):
with VBox():
Canvas(self.painter, data.var)
with HBox():
Button("-").click(self.on_minus)
Label(f"{data.var}").layout(weight=1)
Button("+").click(self.on_plus)
@staticmethod
def painter(canvas, var):
canvas.drawText(var, var/2, f"blah {var}")
canvas.drawLine(var, var, var*2, var*3, color=0xFFFF00)
def on_minus(self):
data.var -= 1
def on_plus(self):
data.var += 1
root = Example()
root.run()
Cookbook
python -m cookbook PySide6 (requires pygments for syntax highlight)
python -m cookbook textual
python -m cookbook flet
python -m cookbook tkinter
Hot Reload
pip install jurigged
Then PUI will take care of view update (code)
Backends
Tier-1
- PySide6
Lower Priority
- wx
- tkinter
- flet
- textual (Text Mode)
- no canvas
Documents
Used by
TODO
- Dump with layout parameters and add test cases
- Toga
- [ISSUE] flet layout sizing (cookbook scroll example)
- nested state trigger
- set state in PUIView init
- set state in setup() ?
- Tabs(
tabposition) - Lazy List
- UI Flow
- Navigation Stack
- View Router
- Model Window/Dialog
- Layout
- SwiftUI style overlay ??
- Canvas
- Arc
- ...
- State with Pydantic support?
Release files for qpuiq 0.44
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qpuiq-0.44.tar.gz | 50.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qpuiq-0.44-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 128.2 kB
Release files / qpuiq-0.44.tar.gz
| Download URL | qpuiq-0.44.tar.gz |
|---|---|
| Size | 50.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
01b76683bd386a8b6f54dd5f45c38101ccf5c4e0fe991b1c1d369f92e5f0999a
|
|
BLAKE2b-256 checksum How to use checksums |
a73008ddf5a8e6bddf5c8921852aaab1067d74d664f25568749e47ef501b8033
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / qpuiq-0.44-py3-none-any.whl
| Download URL | qpuiq-0.44-py3-none-any.whl |
|---|---|
| Size | 77.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a7c2af499978a07727033a5afe115b0f7a1d3e5bfdaa145f52fe718b5ba2ecc0
|
|
BLAKE2b-256 checksum How to use checksums |
97ec5118aa0ca9405021b565a19e8b41cc8c740697b7f8ffc7a480380b4978cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|