Open In App

Building Flutter Apps in Python

Last Updated : 05 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, Here we will use Flutter apps in Python, for this library Flet will help to Build the Application.

What is Flet?

Flet is a Python Library using which developers can build real-time web apps, Mobile Apps, and Desktop apps without directly using Flutter. As to building apps using Flutter, developers need to learn Dart language but using Flet module just using Python codes we can build Apps that will work similarly to apps built in Flutter.

Required Modules:

For this tutorial, we will be using Flet module only. To install it using pip run the following command in the terminal.

pip install flet

We would recommend the user create and use a Virtual Environment for this Tutorial, and install the flet package there.

 

Importing the module:

Python3




import flet as flt
  
def myapp(page: flt.Page):
    pass
  
  
flt.app(target=myapp)


Output:

 

A blank page with default theme opens with this infinitely loading animation as we have nothing in the function till now.

The function’s name can be anything while calling the app method we just have to pass the Target function’s name to include all the features we have mentioned inside of that function is visible in our app.

Running the Program

We can use the traditional method of writing python <file_name.py> to run flet files, but the problem we will face that if we make any change we need to stop the code execution and rerun it, but if we use the flet in front of the filename instead of python, all the changes will be visible instantly.

flet <filename.py>

Remember if the file is not present in the directory we user is currently in, then in place of filename.py user need to provide the full path + filename,py

Changing the Theme of the App

We can also change the theme of the app, either Light or Dark. By default, flet will make the app in the default mode of our device. If our device is in Light Mode it will create the app in Light Mode, if it is in Dark Mode then the app will also be in dark mode.

Python3




import flet as flt
  
def myapp(page: flt.Page):
    page.theme_mode = flt.ThemeMode.DARK # change DARK to LIGHT to convert it to light mode
    page.window_height = 400
    page.window_width = 500
  
    page.title = 'GeeksApp using Flet'
  
    page.update()
  
  
flt.app(target=myapp)


Output:

 

Adding some text into our App

Now we will add some text into our App using the TextField and add method. add method is used to add the widgets or anything we are adding into our app and always keep it updated with our code, if we use add method we can omit the update method we were using previously. But the things we are not adding using the add method like the page title will not be shown as we are not updating the page, so if we only use widgets and we add all of them then we can remove the update method, otherwise we need to keep it. It will not throw any error or anything if we keep both update and add.

Python3




import flet as flt
  
def myapp(page: flt.Page):
    page.theme_mode = flt.ThemeMode.LIGHT
    page.window_height = 400
    page.window_width = 500
  
    text = flt.TextField(
        label="Introductory Text",
        value="This App is made using Flet"
    )
  
    page.add(text)
  
    page.title = 'GeeksApp using Flet'
  
    page.update()
  
  
flt.app(target=myapp)


Output:

 

The TextField method by default comes with a border, we have added a label and its value has been used as Introductory Text which will always be shown in the top left corner of TextField, This App is made using Flet is the value stored in the Textfield. If we want to remove the border we need to add a simple keyword argument in the TextField method.

Python3




text = flt.TextField(
        label="Introductory Text",
        value="This App is made using Flet",
        border = flt.InputBorder.NONE
        )


Output:

 

by default, the value of the border is OUTLINE, if we don’t want to see any border, we will change it to NONE, if we want to only get an underline we will use UNDERLINE.

Python3




text = flt.TextField(
        label="Introductory Text",
        value="This App is made using Flet",
        border = flt.InputBorder.UNDERLINE
        )


Output:

 

TextField can also consist of Numbers, but we have to pass them as Strings.

 We can also add some simple texts by using the Text method inside of add method:

Python3




import flet as flt
  
def myapp(page: flt.Page):
    page.theme_mode = flt.ThemeMode.LIGHT
    page.window_height = 400
    page.window_width = 500
  
    page.add(
        flt.Text("Hello Geeks",
        size = 40,
        color = flt.colors.GREEN,
        bgcolor = flt.colors.YELLOW_300,
        weight=flt.FontWeight.BOLD,
    ))
  
    page.title = 'GeeksApp using Flet'
  
    page.update()
  
  
flt.app(target=myapp)


Output:

 

the text’s size is 40, the color is normally green, the background color is Yellow_300, the greater the number after a color, deeper it looks, and the weight of the font is Bold. 

Simple Calculator using Flet

We will now create a very simple calculator using flet module and whatever we have learned till now with some extra functionalities.

Explanation

  • Firstly imported all the modules and functions we use. All of them belong to flet. No other module will be used here.
  • Then created the main Calculator class which we will use to design the structure, color, padding, width and everything we can see.
  • Two types of buttons are being used here FilledButton and Elevated Button.
    • FilledButton are certain buttons which mostly used to describe important or final actions or end of flow. These kind of buttons have been used here for all the numbers.
    • ElevatedButton – as the name suggests , these are a type of button which remains ‘elevated’ before pressing and if we disable it then it becomes unresponsive (Like those buttons which we can’t press twice, it becomes unresponsive). To express the operators this type has been used. As disabling has not been enabled so it will not be disabled if pressed more than once.
  • Inside both type of Buttons a method on_button_clicked has been passed which will tell what to do if we press certain buttons. Elevated buttons have certain background color and font color but FilledButton doesn’t have them. Also in both case the text parameter holds what will be visible in our calculator and data means what will be put after pressing the button.
  • Then inside the on_button_clicked method all the operations for different operators are defined. Like for addition how the operation will be carried out, same for other available operations.
  • format_number method is used to either print the result in int or as it is (maybe in float with some amount of numbers after decimal place).
  • Then the calculate_value method is used to calculate the values internally for each different available operators. This function is above used inside the on_button_clicked method inside which we have defined what will happen if we press certain buttons.
  • the reset method is of two use. 
    • If the user presses AC on the calculator it will reset everything and display 0.
    • If the user presses ‘=’ then it will erase all other numbers and display only the updated result.
  • myCal function is out of the class CalculatorApp, inside which we will make an instance of that class and modify the width and height of the app we want to display, Note : This will not update the width of the calculator, this will update the width and height of the external window which will be shown after running the code. This is solely created as to run this app we need to use the app method of flet module and pass a function to it.

Python3




import flet
from flet import (
    Column,
    Container,
    ElevatedButton,
    Page,
    Row,
    Text,
    UserControl,
    border_radius,
    colors,
    FilledButton
)
  
  
class CalculatorApp(UserControl):
    def build(self):
        self.reset()
        self.result = Text(value="0", color=colors.WHITE, size=22)
  
        # application's root control (i.e. "view") containing all other controls
        return Container(
            width=325,
            bgcolor=colors.BLUE_900,
            border_radius=border_radius.all(15),
            padding=20,
            content=Column(
                controls=[
                    Row(controls=[self.result], alignment="end"),
                    Row(
                        controls=[
                            ElevatedButton(
                                text="AC",
                                bgcolor=colors.YELLOW_400,
                                color=colors.BLACK,
                                on_click=self.on_button_clicked,
                                data="AC",
                            ),
                            ElevatedButton(
                                text="+/-",
                                bgcolor=colors.YELLOW_400,
                                color=colors.BLACK,
                                on_click=self.on_button_clicked,
                                data="+/-",
                            ),
                            ElevatedButton(
                                text="%",
                                bgcolor=colors.GREEN_900,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data="%",
                            ),
                            ElevatedButton(
                                text="/",
                                bgcolor=colors.GREEN_900,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data="/",
                            ),
                        ],
                    ),
                    Row(
                        controls=[
                            FilledButton(
                                text="7",
                                on_click=self.on_button_clicked,
                                data="7",
                            ),
                            FilledButton(
                                text="8",
                                on_click=self.on_button_clicked,
                                data="8",
                            ),
                            FilledButton(
                                text="9",
                                on_click=self.on_button_clicked,
                                data="9",
                            ),
                            ElevatedButton(
                                text="*",
                                bgcolor=colors.GREEN_900,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data="*",
                            ),
                        ]
                    ),
                    Row(
                        controls=[
                            FilledButton(
                                text="4",
                                on_click=self.on_button_clicked,
                                data="4",
                            ),
                            FilledButton(
                                text="5",
                                on_click=self.on_button_clicked,
                                data="5",
                            ),
                            FilledButton(
                                text="6",
                                on_click=self.on_button_clicked,
                                data="6",
                            ),
                            ElevatedButton(
                                text="-",
                                bgcolor=colors.GREEN_900,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data="-",
                            ),
                        ]
                    ),
                    Row(
                        controls=[
                            FilledButton(
                                text="1",
                                on_click=self.on_button_clicked,
                                data="1",
                            ),
                            FilledButton(
                                text="2",
                                on_click=self.on_button_clicked,
                                data="2",
                            ),
                            FilledButton(
                                text="3",
                                on_click=self.on_button_clicked,
                                data="3",
                            ),
                            ElevatedButton(
                                text="+",
                                on_click=self.on_button_clicked,
                                bgcolor=colors.GREEN_900,
                                color=colors.WHITE,
                                data="+",
                            ),
                        ]
                    ),
                    Row(
                        controls=[
                            FilledButton(
                                text="0",
                                on_click=self.on_button_clicked,
                                data="0",
                            ),
                            FilledButton(
                                text="00",
                                on_click=self.on_button_clicked,
                                data="00",
                            ),
                            ElevatedButton(
                                text=".",
                                bgcolor=colors.AMBER_600,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data=".",
                            ),
                            ElevatedButton(
                                text="=",
                                bgcolor=colors.ORANGE,
                                color=colors.WHITE,
                                on_click=self.on_button_clicked,
                                data="=",
                            ),
                        ]
                    ),
                ],
            ),
        )
  
    def on_button_clicked(self, e):
        data = e.control.data
        if self.result.value == "Error" or data == "AC":
            self.result.value = "0"
            self.reset()
  
        elif data in ("1", "2", "3", "4", "5", "6", "7", "8",
                      "9", "0", ".", "00"):
            if self.result.value == "0" or self.new_operand == True:
                self.result.value = data
                self.new_operand = False
            else:
                self.result.value = self.result.value + data
  
        elif data in ("+", "-", "*", "/"):
            self.result.value = self.calculate_value(
                self.operand1, float(self.result.value), self.operator
            )
            self.operator = data
            if self.result.value == "Error":
                self.operand1 = "0"
            else:
                self.operand1 = float(self.result.value)
            self.new_operand = True
  
        elif data in ("="):
            self.result.value = self.calculate_value(
                self.operand1, float(self.result.value), self.operator
            )
            self.reset()
  
        elif data in ("%"):
            self.result.value = float(self.result.value) / 100
            self.reset()
  
        elif data in ("+/-"):
            if float(self.result.value) > 0:
                self.result.value = "-" + str(self.result.value)
  
            elif float(self.result.value) < 0:
                self.result.value = str(
                    self.format_number(abs(float(self.result.value)))
                )
  
        self.update()
  
    def format_number(self, num):
        if num % 1 == 0:
            return int(num)
        else:
            return num
  
    def calculate_value(self, operand1, operand2, operator):
  
        if operator == "+":
            return self.format_number(operand1 + operand2)
  
        elif operator == "-":
            return self.format_number(operand1 - operand2)
  
        elif operator == "*":
            return self.format_number(operand1 * operand2)
  
        elif operator == "/":
            if operand2 == 0:
                return "Error"
            else:
                return self.format_number(operand1 / operand2)
  
    def reset(self):
        self.operator = "+"
        self.operand1 = 0
        self.new_operand = True
  
  
def myCal(page: flet.Page):
    page.title = "Basic Calculator using Flet"
  
    page.window_height = 375
    page.window_width = 350
  
    calculator = CalculatorApp()
  
    page.update()
  
    # adding application's root control to the page
    page.add(calculator)
  
  
flet.app(target=myCal)


Output:

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads