Introducció
NiceGUI és una llibreria de Python de codi obert per escriure interfícies gràfiques d’usuari que s’executen al navegador. Té una corba d’aprenentatge suau i, alhora, ofereix opcions per a personalitzacions avançades. NiceGUI segueix una filosofia “backend-first”: s’encarrega de tots els detalls del desenvolupament web. Tu et pots centrar en escriure codi Python. Això la fa ideal per a una àmplia gamma de projectes, incloent scripts curts, quadres de comandament, robòtica, solucions IoT, domòtica i aprenentatge automàtic.
NiceGUI s’implementa amb components HTML servits per un servidor HTTP (FastAPI), fins i tot per a finestres natives.
NiceGUI utilitza Vue i Quasar per al frontend, i està construïda sobre FastAPI
Entorn de treball
Crea un projecte amb UV amb el nom gui
:
uv unit gui
Obre el projecte amb PyCharm.
Obre el terminal i afegeix una dependència amb nicegui
:
uv add nicegui
Modifica el fitxer main.py
:
from nicegui import ui
ui.label('Hello World!')
ui.run()
Executa el projecte:
run main.py
Obre el navegador i veu el resultat: http://localhost:8080
Text
ui.label
ui.label
displays some text.
ui.element
Aquesta classe és la base de tots els altres elements de la UI. Però es pot utilitzar per crear elements amb etiquetes HTML arbitràries.
Estil
Tailwind
Pots aplicar classes utilitàries de Tailwind amb el mètode classes
.
ui.label("Tailwind!").classes("text-blue text-2xl font-bold")
NiceGUI ofereix una interfície fluida i amigable amb l’autocompletat per afegir classes de Tailwind als elements de la UI.
ui.label('Auto-Complete').tailwind.font_weight('extrabold').text_color('blue-600').background_color('orange-200')
Pots descobrir les classes disponibles navegant pels mètodes de la propietat tailwind
. El patró de “builder” permet encadenar múltiples classes.
També pots cridar la propietat tailwind
amb una llista de classes.
from nicegui import ui
ui.label("List of classes").tailwind("font-extrabold","text-red-500")
ui.run()
Encara que això és molt similar a utilitzar el mètode classes
, és més còmode per a classes de Tailwind gràcies a l’autocompletat.
Finalment, també pots predefinir un estil i aplicar-lo a múltiples elements:
from nicegui import Tailwind, ui
style = Tailwind().font_weight("extrabold").text_color("red-500")
ui.label("Mercury").tailwind(style)
venus = ui.label("Venus")
style.apply(venus)
ui.run()
CSS
Si realment necessites aplicar CSS, pots utilitzar el mètode style
. Aquí el delimitador és ;
en lloc d’un espai en blanc.
ui.label('Stylish!').style('color: #6E93D6; font-size: 200%; font-weight: 300')
Disseny
Per tal de permetre descripcions de UI intuïtives, NiceGUI fa un seguiment automàtic del context en què es creen els elements. Això vol dir que no hi ha cap paràmetre “pare” explícit. En lloc d’això, el context pare es defineix amb una instrucció with
.
Aquesta decisió de disseny facilita la creació de components modulars que continuen funcionant encara que els moguis dins la UI.
ui.row
ui.row ofereix un contenidor que disposa els fills en una fila.
style = Tailwind().border_width("2").padding("p-2")
ui.label("ui.row")
with ui.row(align_items="end"):
ui.label("Carps are deep-bodied freshwater fishes, typically with barbels around the mouth").tailwind(style)
ui.label("Perch are small freshwater fish known for their distinctive greenish-yellow bodies that feature vertical dark stripes.").tailwind(style)
ui.label("Salmon").tailwind(style)
wrap | si s’ha d’ajustar el contingut (per defecte: False) |
align_items | alineació dels ítems a la columna (“start”, “end”, “center”, “baseline” o “stretch”; per defecte: None) |
ui.column
ui.column ofereix un contenidor que disposa els fills en una columna.
with ui.column(align_items="center"):
ui.label("Cows are herbivorous mammals with cloven hoofs and two horns.")
ui.label("Rabbits are small, furry mammals with long ears, short fluffy tails, and strong, large hind legs.")
ui.label("Cats are small domesticated carnivorous mammals.")
wrap | si s’ha d’ajustar el contingut (per defecte: False) |
align_items | alineació dels ítems a la columna (“start”, “end”, “center”, “baseline” o “stretch”; per defecte: None) |
ui.grid
ui.grid ofereix un contenidor que disposa els fills en una graella.
rows | nombre de files de la graella o una cadena amb la propietat CSS grid-template-rows (p. ex. ‘auto 1fr’) |
columns | nombre de columnes de la graella o una cadena amb la propietat CSS grid-template-columns (p. ex. ‘auto 1fr’) |
with ui.grid(columns=2):
ui.label('Name:')
ui.label('Tom')
ui.label('Age:')
ui.label('42')
ui.label('Height:')
ui.label('1.80m')
Disseny de graella personalitzat
Aquesta demo mostra com crear un disseny de graella personalitzat passant una cadena amb la propietat CSS grid-template-columns. Pots utilitzar qualsevol dimensió CSS vàlida, com ‘auto’, ‘1fr’, etc.
auto
fa que la columna tingui l’amplada del seu contingut.1fr
o2fr
fa que les columnes corresponents omplin l’espai restant, amb fraccions en una proporció 1:2.
with ui.grid(columns='auto 1fr 2fr').classes('w-full gap-0'):
for _ in range(3):
ui.label('auto').classes('border p-1')
ui.label('1fr').classes('border p-1')
ui.label('2fr').classes('border p-1'
Cel·les que abasten múltiples columnes
Aquesta demo mostra com fer que les cel·les abastin múltiples columnes.
with ui.grid(columns=16).classes('w-full gap-0'):
ui.label('full').classes('col-span-full border p-1')
ui.label('8').classes('col-span-8 border p-1')
ui.label('8').classes('col-span-8 border p-1')
ui.label('12').classes('col-span-12 border p-1')
ui.label('4').classes('col-span-4 border p-1')
ui.label('15').classes('col-[span_15] border p-1')
ui.label('1').classes('col-span-1 border p-1')
ui.list
ui.list ofereix un contenidor que disposa els fills en una llista.
Es basa en el component QList de Quasar.
with ui.list().props('dense separator'):
ui.item('3 Apples')
ui.item('5 Bananas')
ui.item('8 Strawberries')
ui.item('13 Walnuts')
Pàgina
@ui.page
Aquest decorador marca una funció com a generadora de pàgina.
Cada usuari que accedeixi a la ruta indicada veurà una nova instància de la pàgina. Això significa que és privada per a l’usuari i no es comparteix amb altres (com passa quan es col·loquen elements fora d’un decorador de pàgina).
path | ruta de la nova pàgina (la ruta ha de començar amb ’/‘) |
title | títol opcional de la pàgina |
viewport | contingut opcional de la metaetiqueta viewport |
favicon | camí relatiu o URL absoluta opcional a un favicon (per defecte: None , s’utilitza la icona de NiceGUI) |
dark | si s’ha d’utilitzar el mode fosc de Quasar (per defecte: l’argument dark de la comanda run ) |
language | idioma de la pàgina (per defecte: l’argument language de la comanda run ) |
response_timeout | temps màxim perquè la funció decorada construeixi la pàgina (per defecte: 3.0 segons) |
reconnect_timeout | temps màxim que el servidor espera que el navegador es reconnecti (per defecte: l’argument reconnect_timeout de la comanda run ) |
api_router | instància d’APIRouter a utilitzar; es pot deixar None per usar la predeterminada |
kwargs | arguments addicionals que es passen al @app.get de FastAPI |
from nicegui import ui
@ui.page('/other_page')
def other_page():
ui.label('Welcome to the other side')
@ui.page('/dark_page', dark=True)
def dark_page():
ui.label('Welcome to the dark side')
ui.link('Visit other page', other_page)
ui.link('Visit dark page', dark_page)
ui.run()
ui.link
ui.link
crea un enllaç a una altra pàgina.
Per saltar a una ubicació específica dins d’una pàgina, pots col·locar àncores enllaçables amb ui.link_target("name")
i enllaçar-hi amb ui.link(target="#name")
.
Paràmetres a la ruta
Les rutes de pàgina poden contenir paràmetres com a FastAPI.
from nicegui import ui
@ui.page('/repeat/{word}/{count}')
def page(word: str, count: int):
ui.label(word * count)
ui.link('Say hi to Santa!', '/repeat/Ho! /3')
ui.run()
Si tenen anotacions de tipus, es converteixen automàticament a valors bool
, int
, float
i complex
.
Si la funció de pàgina espera un argument request
, l’objecte de la petició es proporciona automàticament. L’argument client
dona accés a la connexió websocket, el layout, etc.
Pàgina d’índex automàtica
Les pàgines creades amb el decorador @ui.page
són “privades”. El seu contingut es torna a crear per a cada client. Per tant, a la demo de la dreta, l’ID que es mostra a la pàgina privada canvia quan el navegador recarrega la pàgina.
Els elements de la UI que no estan dins d’una funció de pàgina decorada es col·loquen en una pàgina d’índex generada automàticament a la ruta “/”. Aquesta pàgina d’auto-índex es crea una vegada a l’inici i es comparteix entre tots els clients que s’hi connectin. Així, cada client veurà els mateixos elements. A la demo de la dreta, l’ID que es mostra a la pàgina d’auto-índex es manté constant quan el navegador es recarrega.
from nicegui import ui
from uuid import uuid4
@ui.page('/private_page')
async def private_page():
ui.label(f'private page with ID {uuid4()}')
ui.label(f'shared auto-index page with ID {uuid4()}')
ui.link('private page', private_page)
ui.run()
ui.run
ui.run
Pots cridar ui.run()
amb arguments opcionals. La majoria només apliquen després d’aturar i reiniciar completament l’aplicació i no s’apliquen amb recàrrega automàtica.
Consulta la documentació ui.run
Canvia el títol per defecte de les pàgines:
ui.run(title="xtec.dev")
NiceGUI On Air
Amb ui.run(on_air=True)
pots compartir la teva app local amb altres per Internet 🧞.
En accedir a l’URL “on-air”, totes les llibreries (com Vue, Quasar, …) es carreguen des del CDN de NiceGUI. Així, només cal transmetre el contingut cru i els esdeveniments des de la teva app local. Això ho fa molt ràpid, fins i tot si la teva app només té una connexió a Internet pobra (p. ex. un robot mòbil al camp).
En establir on_air=True
obtindràs una URL aleatòria vàlida durant 1 hora. Si et registres a https://on-air.nicegui.io, pots configurar una organització i un nom de dispositiu per obtenir una URL fixa: https://on-air.nicegui.io/<my-org>/<my_device_name>
.
El dispositiu s’identifica amb un testimoni únic i privat que pots utilitzar en lloc del booleà: ui.run(on_air='<your token>')
.
Si patrocines NiceGUI, habilitaran la gestió multidispositiu i proporcionaran protecció integrada amb contrasenya per a cada dispositiu.
Actualment On Air està disponible com a “tech preview” i es pot utilitzar gratuïtament.