Create a Meditation App in Python with Tkinter

meditation app in python

Introduction

In today’s fast-paced world, it’s easy to get caught up in the chaos of everyday life. Stress, anxiety, and a constant sense of urgency can take a toll on our mental and physical well-being. That’s where meditation comes in. Meditation is like a superpower for your mind and body. It helps you breathe easy, quiet your thoughts, and find inner peace. To make the practice of meditation more accessible and engaging, we can create our own Meditation App.

In this article, we will create a simple yet awesome Meditation App in Python using Tkinter. We’ll build in guided deep breathing exercises with soothing “inhale” and “exhale” sounds playing in the background. No fancy coding skills are needed, just some basic stuff and a little Tkinter magic.

Ready to ditch the stress and embrace the calm? Let’s dive in!

Features of this Application

Wow, at first glance you wouldn’t guess this app was built just with Tkinter! Its design is surprisingly sleek and user-friendly. To get a closer look, check out the screenshots below!

Welcome Window
Main Window

Our mediation app offers the following features:

  1. The default duration for meditation is 60 seconds, equivalent to 1 minute.
  2. You have the flexibility to adjust the duration by using the “Set Time” button to meet your specific needs.
  3. During meditation, the application initiates a 5-second countdown for each ‘inhale’ and ‘exhale’ until the chosen time elapses.
  4. As you meditate, the program will play background status messages such as ‘Relax’ in the initial 4 seconds, ‘Inhale’ during the inhalation phase, and ‘Exhale’ during exhalation.
  5. To end your meditation session, simply press the Home button.

The Project Details

The whole project relies on a pair of Python files, namely ‘app.py’ and ‘settings.py,’ along with two directories, ‘Images’ and ‘Voices.’ Refer to the image provided below for a clearer understanding of the project’s structure:

Project File Hierarchy

Program Files

  • app.py‘: It serves as the primary program file which is responsible for overseeing various functions, especially managing the graphical interface and orchestrating the countdown process for controlling inhalation and exhalation cycles.
  • settings.py‘: It contains all the configuration parameters utilized within the meditation application. This encompasses details like image file paths, font choices, color schemes, default values for specific variables, and more.

Both Python files must exist within the primary directory.

Directories

  • Images‘: This directory serves as the storage location for all the visuals employed in the application.
  • Voices‘: This folder contains a trio of .mp3 files (‘Relax.mp3,’ ‘Inhale.mp3,’ and ‘Exhale.mp3’) intended for playing the status updates during the breathing exercise.

Both folders should be present within the main directory.

Requirements and Installations

If Python isn’t already a resident on your system, fear not! Grab the latest version from their website (https://www.python.org/). Once settled, remember to install Pillow and playsound libraries using the command below. Don’t worry about Tkinter; it’s pre-installed with Python!

pip install Pillow
pip install playsound

Download the Resources

Source Code

I strongly suggest that you download the primary project folder from my GitHub page using the provided Download Button above. It will be in a compressed ‘.zip‘ format. Following that, extract the contents of the file. Inside, you will discover two folders, namely ‘Images‘ and ‘Voices,’ each containing the necessary images and ‘.mp3‘ files.

Next, generate two Python files in the same directory, naming them ‘app.py‘ and ‘settings.py‘ Gather the source code from below and execute the ‘app.py‘ program.

‘app.py’

'''A Meditation Application in Python - Tkinter Project
- developed by Subhankar Rakshit.
'''
import time
import settings as st
from tkinter import *
from threading import *
import multiprocessing as mp
from PIL import ImageTk, Image
from playsound import playsound
from tkinter import ttk, messagebox

class Meditation:
    def __init__(self, root):
        # Window Settings
        self.window = root
        self.window.geometry(f"{st.width}x{st.height}")
        self.window.title('Meditation App')
        self.window.resizable(width = False, height = False)
        self.window.configure(bg=st.color2)

        # Tkinter Frame
        self.frame = Frame(self.window, bg=st.color1, \
        width=800, height=450)
        self.frame.place(x=0, y=0)

        # Default values
        self.inhale = True
        self.exhale = False
        self.onHomePage = False
        self.defaultTime = st.baseTime

        # Calling Home Page
        self.HomePage()

    # Manage the Home/Welcoming Window
    def HomePage(self):
        self.Reset()
        self.ClearScreen()
        self.BgImage(st.bgImage1)
        self.StartButton()
        self.TimeButton()
        self.RemainingTime(self.defaultTime)

    # Function to reset the default values
    def Reset(self):
        self.onHomePage = True
        self.inhale = True
        self.exhale = False
        self.defaultTime = st.baseTime

    # Clear all widgets from the Tkinter Frame
    def ClearScreen(self):
        for widget in self.frame.winfo_children():
            widget.destroy()

    # Displays the background image
    def BgImage(self, img):
        image = Image.open(img)
        resizedImg = image.resize((st.width, st.height))
        self.img1 = ImageTk.PhotoImage(resizedImg)

        label = Label(self.frame, image=self.img1)
        label.pack()

    # Button to Start Meditation
    def StartButton(self):
        image = Image.open(st.startBtn)
        resizedImg = image.resize((130,130))
        self.img2 = ImageTk.PhotoImage(resizedImg)

        self.button = Button(self.frame, image=self.img2, \
        bg=st.color2, border=0, cursor='hand2', \
        command=self.MeditationPage)
        self.button.place(x=320, y=120)

    # Button for setting the duration of mediation 
    def TimeButton(self):
        image = Image.open(st.setTimeBtn)
        resizedImg = image.resize((130,40))
        self.img3 = ImageTk.PhotoImage(resizedImg)

        self.button = Button(self.frame, image=self.img3, \
        bg=st.color2, border=0, cursor='hand2', \
        command=self.SecondWindow)
        self.button.place(x=320, y=270)
    
    # Label to show the remaining time of mediation
    def RemainingTime(self, rTime):
        mins, secs = divmod(rTime, 60)
        self.timeLabel = Label(self.frame, text=f"{mins}:{secs}", \
        bg=st.color2, fg=st.color3 ,font=(st.font3, 15))
        self.timeLabel.place(x=727, y=25)

    # A different window for setting the mediation period
    def SecondWindow(self):
        self.newWindow = Tk()
        self.newWindow.title("Set Time")
        self.newWindow.geometry(st.resolution)

        self.totalTime = IntVar()

        self.chosenTime = ttk.Combobox(self.newWindow, \
        textvariable=self.totalTime, values=st.timeList, \
        font=(st.font3, 20), width=8)
        self.chosenTime.set(1)
        self.chosenTime.place(x=160, y=110)

        setTimeBtn = Button(self.newWindow, text="Set Time", \
        font=(st.font4, 11), bg=st.color5, fg=st.color2, \
        cursor='hand2', command=self.GetTime)
        setTimeBtn.place(x=185, y=150)

    # It takes the time chosen by the user, and calculates in minutes
    # and seconds, and displays on the time label.
    def GetTime(self):
        self.defaultTime = int(self.chosenTime.get()) * 60
        self.newWindow.destroy()

        mins, secs = divmod(self.defaultTime, 60)

        self.timeLabel.config(text=f"{mins}:{secs}")
        self.timeLabel.update()

    # It manages the Mediation/Second page and all its widgets
    def MeditationPage(self):
        self.onHomePage = False
        self.ClearScreen()
        self.BgImage(st.bgImage2)

        self.breathLabel = Label(self.frame, text="", \
        bg=st.color3, fg=st.color2 ,font=(st.font1, 28))
        self.breathLabel.place(x=387, y=172)

        self.statusLabel = Label(self.frame, text="", \
        bg=st.color2, fg=st.color3 ,font=(st.font4, 20))
        self.statusLabel.place(x=360, y=325)

        self.RemainingTime(self.defaultTime)

        # Call the function for Multi-Threading
        self.MultiThreading()

    # Function to create a different thread to handle
    # time management tasks.
    def MultiThreading(self):
        self.x = Thread(target=self.CountDown, daemon=True)
        self.x.start()
    
    # Creates a Tkinter Button to return to the Home/Welcoming Page
    def HomeButton(self):
        image = Image.open(st.homeBtn)
        resizedImg = image.resize((60, 22))
        self.img4 = ImageTk.PhotoImage(resizedImg)

        self.button = Button(self.frame, image=self.img4, \
        bg=st.color3, border=0, cursor='hand2', command=self.HomePage)
        self.button.place(x=20, y=20)

    # Function to handle time management tasks
    def CountDown(self):
        try:
            self.UpdateStatus("Relax!")
            process = self.PlayVoice(st.Relax)
            time.sleep(4)
            process.terminate()

            self.HomeButton()

            while self.defaultTime > 0:
                # Inhale CountDown
                if self.inhale:
                    # A separate process to play 'Inhale' voice
                    process = self.PlayVoice(st.Inhale)
                    # Countdown inhale time
                    self.CountInhale()
                    # Terminate the process
                    process.terminate()

                # Exhale CountDown                  
                elif self.exhale:
                    # A separate process to play 'Exhale' voice
                    process = self.PlayVoice(st.Exhale)
                    # Countdown exhale time
                    self.CountExhale()
                    # Terminate the process
                    process.terminate()

                # Time is up
                if self.defaultTime <= 0:
                    self.UpdateStatus("Done!!")
                    self.UpdateTime(0, 0)

                # To Break the outer loop:
                # If the user presses the Home button 
                # during meditation.
                if self.onHomePage:
                    break

        # Catch and display any exceptions, if arises.
        except Exception as es:
            messagebox.showerror("Error!", f"Error due to {es}")

    # Function to Count Inhale time repeatedly 
    # until the time ends up.
    def CountInhale(self):
        self.inhale = False
        self.exhale = True

        # getting the default inhale time
        inhale = st.inhaleTime

        # Update the Status with 'Inhale' text
        self.UpdateStatus("Inhale")

        while inhale > 0:
            # To Break the inner loop: If the user presses 
            # the Home button during inhaling.
            if self.onHomePage:
                break
            else:
                # Update the remaining time of meditation
                mins, secs = divmod(self.defaultTime, 60)
                self.UpdateTime(mins, secs)

                # Update the remaining inhale time
                self.UpdateBreathTime(inhale)

                # Decrease time by 1 per second
                inhale -= 1
                self.defaultTime -= 1
                time.sleep(1)

    # Function to Count Exhale time repeatedly
    # until the time ends up.
    def CountExhale(self):
        self.exhale = False
        self.inhale = True
        
        # getting the default exhale time
        exhale = st.exhaleTime

        # Update the Status with 'Exhale' text
        self.UpdateStatus("Exhale")

        while exhale > 0:
            # To Break the inner loop: If the user presses 
            # the Home button during exhaling.
            if self.onHomePage:
                break
            else:
                # Update the remaining time of meditation
                mins, secs = divmod(self.defaultTime, 60)
                self.UpdateTime(mins, secs)

                # Update the remaining exhale time
                self.UpdateBreathTime(exhale)

                # Decrease time by 1 per second
                exhale -= 1
                self.defaultTime -= 1
                time.sleep(1)

    # Function to update the status: Inhale/Exhale
    def UpdateStatus(self, msg):
        self.statusLabel.config(text=msg)
        self.statusLabel.update()

    # Function to update the remaining time
    def UpdateTime(self, mins, secs):
        self.timeLabel.config(text=f"{mins}:{secs}")
        self.timeLabel.update()

    def UpdateBreathTime(self, breath):
        self.breathLabel.config(text=f"{breath}")
        self.breathLabel.update()

    # It plays a .mp3 file to express the current
    # status of meditation: 'Inhale' or 'Exhale'.
    def PlayVoice(self, voice):
        process = mp.Process(target=playsound, args=(voice,))
        process.start()
        return process

# The main function
if __name__ == "__main__":
    # Instance of Tk class
    root = Tk()
    # Object of Meditation class
    obj = Meditation(root)
    root.mainloop()

‘settings.py’

'''Variables used in 'app.py' are present here.
'''
# Screen Size
width = 800
height = 450

# Secondary screen size
resolution = "480x320"

# Background Images
bgImage1 = "Images/BgImage_1.png"
bgImage2 = "Images/BgImage_2.png"

# Button images
startBtn = "Images/StartBtn.png"
setTimeBtn = "Images/SetTimeBtn.png"
homeBtn = "Images/HomeBtn.png"

# List of Time in minutes. You can modify it.
timeList = [1, 3, 5, 7, 10]

# Default inhale and exhale time in seconds. 
# Try to keep it as it is. Inhale+Exhale = must be 10.
inhaleTime = 5
exhaleTime = 5

# Default meditation time in seconds
baseTime = 60

# Font choices
font1 = "Times new roman"
font2 = "Helvetica"
font3 = "Courier"
font4 = "Kokila"

# Color choices
color1 = "#63afdb"
color2 = "white"
color3 = "black"
color4 = "yellow"
color5 = "green"
color6 = "sky blue"

# Voice Cover
Relax = "Voices/Relax.mp3"
Inhale = "Voices/Inhale.mp3"
Exhale = "Voices/Exhale.mp3"

Output

Watch the video to see how the Meditation App works:

Summary

In this article, we’ve created a simple Meditation App in Python using the Tkinter library. It provides the following functionalities for the user:

  1. Users can customize the meditation duration to their preference.
  2. It continuously alternates between 5 seconds of inhalation and 5 seconds of exhalation until the selected time elapses.
  3. For added user convenience, it incorporates voice prompts (‘inhale’ or ‘exhale’) to keep users informed about their current breathing phase.

This application is incredibly user-friendly and can be used anytime, anywhere. It’s particularly beneficial during extended computer work sessions when outdoor breaks aren’t possible, as it can swiftly enhance your breathing rhythm, reducing anxiety and stress in a short period.

For more interesting Tkinter examples, please explore the dedicated page exclusively made for Python Projects. Here are a few examples to spark your interest:

Happy meditating!

Share your love
Subhankar Rakshit
Subhankar Rakshit

Hey there! I’m Subhankar Rakshit, the brains behind PySeek. I’m a Post Graduate in Computer Science. PySeek is where I channel my love for Python programming and share it with the world through engaging and informative blogs.

Articles: 147