Home Artificial Intelligence Meet the NiceGUI: Your Soon-to-be Favorite Python UI Library Hands-On

Meet the NiceGUI: Your Soon-to-be Favorite Python UI Library Hands-On

0
Meet the NiceGUI: Your Soon-to-be Favorite Python UI Library
Hands-On

Construct custom web apps easily and quickly

Towards Data Science
Photo by Alexander Schimmeck on Unsplash

Meet NiceGUI, a straightforward Python-based UI framework that works easily together with your web browser or as a desktop app. Whether you’re making small web apps, dashboards, or fidgeting with robotics projects, NiceGUI makes it easy with its easy interface and plenty of features.

The goal of this post is to persuade you to try it out by listing the professionals and cons of this library by showing you ways you possibly can construct and deploy a NiceGUI app. (This shouldn’t be a sponsored post, I similar to the library 🙃)

Streamlit vs. NiceGUI: Why Switch?

While Streamlit is sweet for making interactive apps, it will probably be tricky to handle events and states, especially for larger projects. NiceGUI is different. It enables you to control states and interactions directly, while not having extra steps or hacky workarounds.

Easy State Management

NiceGUI makes managing states easy. Unlike Streamlit, which might reset states unexpectedly, NiceGUI keeps things regular, whether it’s the starting state or changes made by users. You need to use callbacks to handle user interactions in event-based manner without getting annoyed by a full page refresh and losing state data.

A lot of Features

NiceGUI has many cool features:

  • Buttons, switches, sliders, inputs, and more for interaction.
  • Easy ways to rearrange things on the screen.
  • Charts, tables, and even 3D scenes for visuals.
  • Integration with data visualization libraries like Matplotlib or Plotly.
  • Customize colours and styles easily.
  • Tools to assist with coding and testing.
  • Important devs are all the time available to reply questions and are very receptive to feedback on their GitHub space.
  • Construct on top of popular frameworks: FastAPI, Vue3, Tailwind, Quasar.
  • Their whole site is made with the NiceGUI library: https://nicegui.io/documentation

Limitations

While NiceGUI is great, it’s value noting that its smaller community size is likely to be just a little limiting. It also has a rather longer learning curve in comparison with more popular frameworks like Streamlit. It’s preferable to get acquainted with CSS and Tailwind CSS to profit from the library’s features. Also, knowledge of FastAPI, Vue and Quasar can offer you greater flexibility and extend what you possibly can implement.

Now, lets explore some features of NiceGUI after which construct and deploy a demo app.

Basic app

First install NiceGUI:

pip install nicegui[highcharts]

Lets start from an example from the important documentation:

# https://nicegui.io/documentation/section_data_elements
from nicegui import ui
from random import random

chart = ui.highchart({
'title': False,
'chart': {'type': 'bar'},
'xAxis': {'categories': ['A', 'B']},
'series': [
{'name': 'Alpha', 'data': [0.1, 0.2]},
{'name': 'Beta', 'data': [0.3, 0.4]},
],
}).classes('w-full h-64')

def update():
chart.options['series'][0]['data'][0] = random()
chart.update()

ui.button('Update', on_click=update)

ui.run()

Here, the UI module is what’s going to help you create a UI element.
In this instance, first we create a highchart element, we assign to it the tailwind classes w-full and h-64. w-full will make it use the entire screen horizontally in a response manner and h-64 specifies the peak.

Image by creator

After we click on the button, a callback function is triggered. This callback will update the info used for the chart after which re-renders it in a fluid manner.

It’s also possible to change the callback so as to add latest bars:

def update():
chart.options["xAxis"]["categories"].append(random.selection(string.ascii_uppercase))
for series in chart.options['series']:
series["data"].append(random.random())
chart.update()
Image by creator

Also, notice that refreshing the page doesn’t make you lose your data! You’ll be able to’t do this with another Python UI libraries. The rationale why it really works that way here is that data is shared amongst all users, but there are plenty of ways to maintain data user-specific just like the app.storage.user object or app.storage.browser (when wrapped around a @ui.page decorator).

But, what if you would like to update the UI on a recurrent timer? easy ! Just change the button element to ui.timer

ui.timer(5, callback=lambda: (update(), ui.notify("Data Updated")))
Image by creator

Now, allow us to construct a demo app that lets users pick a category then allows them to generate a random Chuck Norris Fact.

First, here is the important code:

import requests  # Importing the requests library to make HTTP requests
from nicegui import ui # Importing UI components from the NiceGUI library
from nicegui_app.header import add_head_html # Importing a function so as to add HTML head content

# List of categories for Chuck Norris facts
CATEGORIES = [
"animal",
"career",
"celebrity",
"dev",
"fashion",
"food",
"money",
"movie",
"music",
"science",
"sport",
"travel",
]

# Class to handle Chuck Norris facts
class Fact:
def __init__(self):
self.fact = None # Initialize the very fact attribute to None

# Method to update the very fact based on a given category
def update_fact(self, category):
url = f"https://api.chucknorris.io/jokes/random?category={category}" # URL to Chuck Norris API

for i in range(10): # Try as much as 10 times to fetch a legitimate fact
result = requests.get(url) # Make a GET request to the Chuck Norris API

if result.status_code == 200: # If the request is successful
result_json = result.json() # Parse the JSON response
if self.fact != result_json["value"]: # If the fetched fact is different from the present one
self.fact = result_json["value"] # Update the very fact attribute
break # Exit the loop

# Function to generate the Chuck Norris fact UI
def chuck():
add_head_html() # Add HTML head content for the NiceGUI app

default_value = CATEGORIES[0] # Default category for Chuck Norris facts

fact = Fact() # Create an instance of the Fact class
fact.update_fact(default_value) # Update the very fact using the default category

# Create a grid layout with 12 columns
with ui.grid(columns=12).classes("w-full"):
# Column for category selection
with ui.column().classes("col-span-4 sm:col-span-2 space-x-0"):
ui.label("Pick a fact category:") # Display a label for category selection
# Radio button group for choosing categories
category = ui.radio(
CATEGORIES,
value=default_value,
on_change=lambda _: fact.update_fact(category.value), # Update the very fact when the category changes
).classes("w-full")
# Button to regenerate the very fact for the chosen category
ui.button(
"⟳ Re-Generate", on_click=lambda _: fact.update_fact(category.value)
)

# Column for displaying the Chuck Norris fact
with ui.column().classes(
"flex col-span-8 sm:col-span-10 w-full justify-center mx-auto max-w-screen-md"
):
# Label to display the Chuck Norris fact, certain to the very fact attribute of the Fact instance
ui.label().bind_text_from(fact, "fact").classes(
"text-lg sm:text-3xl text-gray-800 bg-gray-100 rounded-lg shadow-lg p-6"
)

Now allow us to undergo it step-by-step:

First, we make the vital imports and define the possible categories.

Then, we define the category that can store and update our random fact:

class Fact:
def __init__(self):
self.fact = None # Initialize the very fact attribute to None

# Method to update the very fact based on a given category
def update_fact(self, category):
url = f"https://api.chucknorris.io/jokes/random?category={category}" # URL to Chuck Norris API

for i in range(10): # Try as much as 10 times to fetch a legitimate fact
result = requests.get(url) # Make a GET request to the Chuck Norris API

if result.status_code == 200: # If the request is successful
result_json = result.json() # Parse the JSON response
if self.fact != result_json["value"]: # If the fetched fact is different from the present one
self.fact = result_json["value"] # Update the very fact attribute
break # Exit the loop

This class stores the very fact within the attribute “fact” and has a technique update_fact that calls the Chuck Norris facts api. https://api.chucknorris.io

Next, we define our page within the “chuck” function. NiceGUI adopts a modular approach that enables you to define your app over multiple modules and python files.

We define an instance of our data class fact = Fact() That is a selected instance to every user. Next, we init the very fact using the update_fact method.

Now, we start defining our UI elements.

We define a grid with two columns:

  • A primary column that has our category options and generate button. This one has the next tailwind classes: col-span-4 sm:col-span-2. It implies that for very small screens it should use up 4/12 of the screen, otherwise it should use up 2/12. This makes the design work in mobile phones too.
  • A second column where we’ll display the very fact.

For the primary column:

  • A radio menu ui.radio.
  • A button to generate a random fact.

Each elements, when clicked or modified will use a callback that calls fact.update_fact

For the second column:

  • Now we have a ui.label that binds its value to fact.fact so every time this variable changes, it should update the display mechanically.

The label has the next tailwind classes: text-lg sm:text-3xl This makes it so the text is smaller on small screens.

This provides you the next app:

Image by creator

Neat! right?

Deployment

Deploying such app is straightforward! Using CloudRun for instance. You only need to create a Dockerfile after which run the next gcloud instructions:

PROJECT_ID=$(gcloud config get-value project)
REPO="demo"
LOCATION="europe-west1"
IMAGE="nicegui_app"
SERVICE_NAME="nicegui-app"
VERSION="0.0.1"
GAR_TAG=$LOCATION-docker.pkg.dev/$PROJECT_ID/$REPO/$IMAGE:$VERSION

# Create repository
gcloud artifacts repositories create $REPO --repository-format=docker
--location=$LOCATION --description="Docker repository"
--project=$PROJECT_ID || true # If fails because exist already then its advantageous

# Construct image
gcloud builds submit --tag $GAR_TAG

# Deploy Cloud run
gcloud run deploy $SERVICE_NAME --image=$GAR_TAG --max-instances=1 --min-instances=0 --port=8080
--allow-unauthenticated --region=europe-west1 --memory=0.5Gi --cpu=1 -q --no-cpu-throttling --session-affinity

This builds the docker image using cloud construct after which deploys it to CloudRun.

The one key options listed below are: “ — no-cpu-throttling — session-affinity” This permits the identical user to be routed the identical container when possible and keeps the CPU alive between requests. You’ll be able to try it out here: https://nicegui-app-dfmj3maizq-ew.a.run.app/

In Conclusion

NiceGUI is an excellent selection if you would like to make user interfaces quickly and simply with Python. It’ll assist you to construct powerful python apps where you keep full control of the inner state and that you could test and deploy easily. Hopefully, it will probably help you express your creativity in your data science projects without being limited by tools.

What was shown here is only a small fraction of what you possibly can do with NiceGUI. You’ll be able to learn more by following the links below.

Resources:

LEAVE A REPLY

Please enter your comment!
Please enter your name here