Flet: Power of your favourite language + Flutter UI

The user interface is one of the most important cornerstones of any application and developing one requires knowledge of a frontend framework. This blog explores a new promising framework 'Flet' which helps develop UI in a language you probably already know.

Flet: Power of your favourite language + Flutter UI

The user interface is one of the most important cornerstones of any application. If we want to develop any frontend, ideally we will have to learn a frontend framework like React/Vue, etc which has a huge learning curve. And a conventional full-stack software development process always needs guys who we call the front-end gurus, the experts in HTML, CSS, JS, and the list goes on. But why do we need so many languages to create a product ?

Because we’ve no other options. Source: Reddit

But recently few frameworks came into existence where you can use one language for both front-end and back-end such as Kotlin, and Dart (Flutter). And again you’ve to learn a new language and its fundamentals to get started. But what if there’s a framework that enables developers to develop UI in a language they already know? And here’s come our saviour called ‘Flet’.

What is Flet?

So let’s get started with the much-awaited question what is Flet?

It is a framework that helps us to build a cross-platform application that runs on the web, desktop, and mobile without any prior knowledge of front-end development. Flet is very different from other front-end frameworks. And it's not just a module or library to an existing framework. It's something built from scratch and uses Flutter underneath to create beautiful and professional UIs.

Credit: Abhishek Salian (Fellow Codemonker)

Flet UI is built with very similar controls to Widgets in Flutter. But Flet controls are not just wrappers around Flutter widgets, it’s much simpler by hiding the complexities and combining smaller widgets. But how?

So, Flet is not about copying the widgets in any language or transpiling of code. It’s more about representing the basic building components of Flutter in a language-specific form and flattening the hierarchy of the Flutter widget tree. So, how does Flet work without transpiling the code? Let’s look into the architecture.

This is the part where things get more interesting.

The architecture of a Flet app.
The architecture of a Flet app.

Every Flet app is a web app and even if it's opened in a native OS window, it has a built-in web server called ‘fletd’ that is written in Go. This server serves as the middle-end for the user program and Flutter client. And this Flet server is solely responsible for storing the current states and data of the Flet controls and updating the UI. But this complex architecture doesn't answer all our questions regarding using Flet. Let’s take a deep dive into the usage of Flet.

So, Why use Flet?

We’ve seen framework like PyQT in Python and Swing in Java which uses only one programming language but Flet is something more than that. Flutter has proved to be the best by enabling developers to create UI faster and compiling into the native code and Flet picks these features and combines them with any language. But why can’t we use Flutter with Dart instead? Well, let me help you with that. Here’s how simple “Hello World” would look in Flutter. Flutter/Dart uses a declarative style of programming, with various complex states and architecture.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

In order to show new data in a Widget (UI component), you’ve to update the state of the class with method calls. A bit too much, right? But Flet uses an imperative style of programming instead of updating the states of a class. Flet focuses on updating the value of its controls (UI component), which in turn updates the UI.

Flet has already released its initial version to support Python. Yes, you heard me right! Flet = Python + Flutter Widgets. This is how Python Calculator looks like now with Flutter UI.

Untitled.png
Source: Flet Docs

And this is how it looked like without Flutter.

pycalc.9572fb3104cb.gif
Source: Real Python

And it has a roadmap to support languages too.

Getting started

To start developing with Flet, you just need your favorite IDE, a little knowledge about Python programming, and Flutter Widgets. Flet has a built-in web server with assets hosting and desktop clients. So you don’t have to worry about installing SDKs, dependencies, and complex tools to get started. No more Flutter Doctor.

Source: https://imgflip.com/
Source: https://imgflip.com/

If you’re familiar with basic Python, you’ll have an idea about Python packages and modules and how to add them to your Python project. Just like any other Python package, you can install Flet by using the command below:

pip install flet

Python has always proved to be one of the most powerful languages with amazing capabilities. Let’s explore how powerful it is for creating UI as well. So, we will start by building a simple app.

Sample App

By the way, have you watched the ‘Silicon Valley’ comedy series on HBO? If so, I bet you remember the Not Hot Dog app that Jian Yang developed. For those who don’t know, it's an app that distinguishes whether a dish is Hot Dog. Let's develop the same using Flet.

Flet enables us to use the Python language's raw power and UI in Flutter. Additionally, you can use any packages or modules that are available in Python.

So, Let’s move to the implementation now. First, we’re gonna develop a simple “Hello World” just to get an understanding of the Flet program structure.

import flet

def main(page: flet.Page):
		text = flet.Text("Hello World!", size=24, color="black", weight="bold")
		page.add(text)

flet.app(target=main, assets_dir="assets")

Page is the topmost control in Flet. You can add more controls to a Page that form a tree just like the widget tree in Flutter. And this tree can be updated using the update() method in Page which is very similar to setState() in Flutter.

Before getting into the complex coding, we will follow the simple wireframe below for the UI implementation.

Lo-fi  UI of the app
Lo-fi UI of the app

This app is a single-page app and we can wrap it inside a single Python file, which will be our “main.py

We will import all the required modules

import flet
import label_dog

We will be using an already developed TensorFlow model named ‘label_dog’ by VPanjeta (https://github.com/VPanjeta/hotdog-or-not-hotdog). The model was trained to classify whether the picture is of a hot dog or not. Let’s not deep dive into the model just remember that the model takes an image and returns whether it’s a hot dog or not. And here is how it’s done.

result = label_dog.hot_dog_or_not(file_path)

First, we’re going to set up a Flet control to display an image and for that, we will need an Image control.

hot_dog_image_path = f"/images/cool_hot_dog.png"

def main(page: flet.Page):
    selected_image = flet.Image(
        height=325,
        width=325,
        src=hot_dog_image_path,
        border_radius=20,
        fit="contain",
    )

We need a footer and two text controls and wrap them under a single Column.

loading_text = flet.Text("",size=20, color="black", weight="bold")
		footer_text= flet.Container(flet.Text("Built with 💕 in India\\n",size=13, color=flet.colors.BLUE_GREY_800,
                       weight="w400",) ,padding=16,)
    intro_text1 = flet.Text("See Food", size=24, color="black", weight="bold")
    intro_text2 = flet.Text("We help you to identify hot dogs using our proprietary algorithm,\\n"
                       "See Food is built with Python and power of Flet.\\n"
                       "Built with 💕 in India\\n\\n"
                       "Join our journey to make the world a better place\\n", size=13, color=flet.colors.BLUE_GREY_800,
                       weight="w400",
                       )
		

    intro_text = flet.Container(flet.Column(
        [
            intro_text1,
            intro_text2

        ],
        wrap=True,
        tight=True,
        alignment="center",
        horizontal_alignment="start"
    ),
        padding=16,
        width=page.width / 3,
        height=300,
    )

Now for the whole UI, we have to add the image control and the intro text inside a Row.

intro_container = flet.Container(flet.Row(
        [
            flet.Container(
                selected_image
            ),
            intro_text
        ],
        wrap=True,
        tight=True,
        alignment="start",
        vertical_alignment="start"
    ), width=page.width
    )

Now the last control is a button, which will be used to pick a file.

button_default = flet.Container(flet.FilledTonalButton(text="Upload File",
                                                      height=50,
                                                      on_click=lambda _: pick_files_dialog.pick_files(
                                                          allow_multiple=False
                                                      ),
                                                      ),
                               )

But the button needs an action to be triggered upon pressing it. We will add a function for the task and attach it to Button’s onPressed event.

def pick_files_result(e: flet.FilePickerResultEvent):
        loading_text.value="Loading. Please wait."
        page.update()
        text = label_dog.hot_dog_or_not(e.files[0].path)
        global hot_dog_image_path
        if text == "hot dog":
            hot_dog_image_path = f"/images/positive.png"
            intro_text1.value = "Yeah !! It's a hot-dog 😁"
        else:
            hot_dog_image_path = f"/images/negative.png"
            intro_text1.value = "Oops !! Not a hot-dog 🥹"
        selected_image.src = hot_dog_image_path
        intro_text2.value = "Pick another file to try again"
        loading_text.value=""
        selected_image.update()
        page.update()

This function updates the file_path and **value of intro_text1 based on the results.

And for the final touch, let’s fix some alignment and add all the controls to the Page with an AppBar. And that’s it 😅.

pick_files_dialog = flet.FilePicker(on_result=pick_files_result)
    page.overlay.append(pick_files_dialog)
    page.horizontal_alignment = 'center'
    page.vertical_alignment = 'center'
    page.bgcolor = "white"

    page.add(
        flet.AppBar(
            title=flet.Text("Welcome", size=24, color="black", weight="bold", ), bgcolor="white"),
        flet.Column(
            [
                intro_container,
                loading_text,
                button,
footer_text
            ],
            wrap=True,
            tight=True,
            alignment="center",
            horizontal_alignment="center"
        )
    )

flet.app(target=main, assets_dir="assets")

Running the Flet app

So the most exciting part is to see the app.

If you’re already into Python, you would know how to run a Python program. Just use the prefix Python with a file name as a suffix. Trust me nothing is as easy as this.

python main.py
Source of image in app : https://www.seekpng.com/ipng/u2e6a9q8y3e6y3y3_hot-dog-cartoon-royalty-free-clip-art-hot/
Source of image in app: https://www.seekpng.com/ipng/u2e6a9q8y3e6y3y3_hot-dog-cartoon-royalty-free-clip-art-hot/

You can upload an image file using the file picker which is a Flutter widget. After picking the file the TensorModel will classify whether it’s a hot dog or not. Here’s the video of what we’ve achieved using Flet.

0:00
/

But a normal user won’t run software using these commands. The Flet app should be installable just like any other software running on your mobile or desktop. To make this program an installable file.

Export as an installable app or bundle

PyInstaller bundles a Python application and all its dependencies into a single package. To bundle a Python application to a Windows package, PyInstaller must be run on Windows, to build a Linux app, it must be run on Linux, and to build a macOS app - on macOS.

pip install pyinstaller

Go to the directory where your .py file is located and build your app with the following command:

pyinstaller main.py

On macOS/Linux:

./dist/your_program/main

on Windows:

dist\\your_program\\main.exe

Flet Python app and all its dependencies can be packaged into an executable and users can run it on their computer without installing a Python interpreter or any modules.

Conclusion

Flet is a Server-driven UI (SDUI) framework. Companies like Lyft and Airbnb have already implemented this architecture for their apps to reduce their time-to-market. But what makes Flet unique is that there plan to support all the widely used languages to create a full stack app using just the language you know. And on top of that Flutter backed by Google has already been used in developing applications by top companies around the globe. And a mixture of Flutter and your favourite language will be unstoppable.

You can also refer to our sample app repository - https://github.com/CodemonkHQ/see-food.git

References:

  1. https://flet.dev/
  2. https://github.com/VPanjeta/hotdog-or-not-hotdog
  3. https://docs.flutter.dev/development/ui/widgets
Subscribe