project / July 14th, 2021
The Pomodoro Timer is a Graphical User Interface (GUI) desktop app built in Python using the Tkinter library. This is a productivity app!
Whenever an individual is thinking of work they don't want to do, the pain centers of their brain are activated. Naturally, the brain attempts to stop this negative stimulation by turning its attention to something else and procrastination occurs.
In the late 1980s, Francesco Cirillo created the Pomodoro Technique to combat procrastination and minimize the effects of potential distractions. This is a time management method in which an individual chooses a task to be completed and a timer is used to break down the work into 25 minute intervals called pomodoros. After a pomodoro is completed, a short 5-10 minute break is taken and the process repeats until three or four pomodoros are completed. At this point, a long 20-30 minute break is taken and the entire process is repeated from zero pomodoros until the task is completed.
The Pomodoro Timer app applies the principles of the Pomodoro Technique. After the user presses the start button, the timer for the first 25-minute pomodoro begins and text is displayed to prompt the user to start working. After a pomodoro is completed, the GUI window will pop-up (if minimized) and display a checkmark below the timer to denote that one pomodoro has been completed. A 5-minute timer for a short break automatically starts and the app continues to alternate between the 25-minute and 5-minute timers until the fourth pomodoro is completed. After the fourth pomodoro is completed, a 20-minute long break timer is started and the four checkmarks below the timer are erased in preparation for another set of pomodoros. The user also has an option to reset the timer and their number of completed pomodoros at any time they choose.
This was one of the first GUI projects I built in the 100 Days of Code Python Bootcamp, as part of the Tkinter module.
This project was devised as part of the 100 Days of Code Python Bootcamp to introduce the concept of building GUI applications using the Tkinter library in Python. Students apply what they have learned about adding and configuring Tkinter widgets like labels, buttons, and canvas to the GUI and combine it with programming techniques from previous modules to implement the timer functionality. However, the most important skill to learn from this project is learning how to read the Tkinter documentation in order to customize the app the way I see fit.
Python
Tkinter
PyInstaller
NSIS
For the most part, I did not deviate much from the original project since it was my first time building a GUI app with Tkinter. However, the Tkinter documentation was used at various points throughout the project to learn how to customize the behaviour and appearance of the buttons and text differently. I changed the colour and relief attribute of the start and reset buttons from the default setting to add more definition and make it appear less sunken on-screen. I also used a different text font and changed the timer labels to be more descriptive.
The most significant modification I made was changing the behaviour of the start button to be disabled when pressed and the timer starts. Subsequent clicks of the start button will have no effect and will only work again after the reset button is pressed. The reason I made this change was because I noticed that pressing the start button after the initial press messes up the timer.
After completing the project, I wanted to be able to use it without having to open up PyCharm every single time. This topic was not covered in the bootcamp, so I watched this useful YouTube video on how to use the PyInstaller library or NSIS software to convert Python files into executable files.
The first step was to set up the User Interface (UI) by using Tkinter to create and run a new window with a title and background colour. In order to insert the tomato image into the window and overlay it with text which will be the countdown timer, a Tkinter canvas widget is used. The canvas has its own methods like create_image and create_text to allow components like images and text to be layered on top of each other. After using the PhotoImage Tkinter class to read the tomato image, it can be placed on the center of the canvas, which uses the grid system and is set to have the same dimensions as the image. This is followed by overlaying the timer text (which has a default value of 00:00) over the tomato image. The rest of the UI is completed by adding label widgets for the title above the timer to denote what the user should be doing and the checkmark counter below the timer to count the number of completed pomodoros. Button widgets for the start and reset functions are also added to the grid and customized. Finally, adjustments to the fonts and colours are made to fit my preferences.
The second step is to add functionality for the timer. Since this app is meant to be an event-driven GUI program that is constantly looping, refreshing, and listening for events thanks to a Tkinter window method called mainloop that is placed at the end of the program, another loop (like one used to count down time) cannot be used inside the program. This would result in the program bring unable to reach the mainloop, which is necessary for it to launch.
A different approach is necessary. By using a built-in widget method called after, a specified amount of time, a function, and the arguments of the function can be passed to the widget. After the specified amount of time has passed, the function will be called. This can help create looping behaviour by creating a function called count_down, and then using the window's after method inside the function to have count_down call itself. count_down will have an argument called count which represents the timer length and will be one of three values - 25, 20, or 5 minutes (in seconds). The number of minutes and seconds shown in clock format will be calculated from count using the floor and modulo methods, and the timer text will display these values using the canvas itemconfig method. If the count argument remains greater than 0 seconds, the countdown function will continue to call itself and pass a timer length with 1 less second. If the count argument is equal to 0, the window will pop-up (if minimized), a method called start_timer is called to pass a different timer length to count_down, and the number of completed pomodoros checkmarks will be updated if the 25-minute timer just expired. If four pomodoros were completed, the pomodoro counter will reset.
The third step is to write code for the start_timer function, which will be called when the start button is clicked or when the timer length in count_down reaches 0. This function is responsible for changing the label above the timer, disabling the start button, calling the count_down function when a new timer starts, and using the current number of timer completions (which is globally accessible) to determine which new timer length should be passed to count_down.
Finally, the reset_timer function is created and is called when the reset button is clicked. Clicking reset means the start button is no longer disabled, the timer set up using the after method is cancelled, the timer text reverts to the default 00:00, the label above the timer reverts to the default "pomodoro timer", and the number of completed pomodoro checkmarks are cleared. The app is now complete!
To turn the app into an executable file, the PyInstaller library is used. The NSIS library can also be used to turn the entire project folder into a compact downloadable package.
Personally, it felt extremely rewarding to built a Pomodoro app because I previously learned about the Pomodoro Technique in a Mindshift Personal Development course I took before learning about programming. It was interesting to see these two seemingly unrelated worlds become connected and to be able to create a useful application that I now use frequently.
Although writing code for the timer functionality was challenging to understand, I'm happy that I pushed through it. It gives me confidence knowing that I can understand complex code when I invest enough time in it.
I really like the simplicity of the app in its current form, but a possible suggestion would be to keep a record of the number of pomodoros done in previous days and add a button to display it. Everybody has off days, and looking at a record of previous pomodoros can be motivating if one hasn't done as many as they would like recently.
Another useful improvement would be to center and scale the size of the widgets if the user chooses to change the window size, if possible! It would add a tiny bit more flexibility.