Expense Tracker Application using Tkinter in PythonIn the following tutorial, we will develop a Graphical User Interface (GUI) based Expense Tracker application with the help of the Tkinter, Tkcalendar, and SQLite libraries. It is an intermediate-level project where we will learn a lot about databases and GUIs and their implementation in real life. So, let's get started. What is an Expense Tracker?There are many people in India that live on a fixed income, and they find that towards the end of the month, they don't have sufficient money to meet their needs. While this issue can arise because of low salaries, it is due to poor money management skills. Expense Tracker, also known as Expense Manager and Money Manager, is a desktop application or software allowing users to record their money inflow and outflow accurately. People tend to overspend without understanding, which can prove to be dreadful. We can keep track of our daily expenditures with the help of a daily expense tracker. By the end of the month, we will have a clear picture displaying the flow of money. This is among the best ways to get the expenses under management and bring some semblance of order to the finances. About the ProjectThis project aims to build an Expense Tracker based on GUI. In order to build this, we will require an intermediate knowledge and understanding of the Tkinter library, SQL language and its commands, and fundamental knowledge of different modules of the Tkinter library and the tkcalendar library. Prerequisites of the ProjectThere are some libraries and modules that we will need in the creation of the GUI Assistant Application in Python. These modules are briefly described as follows:
Since Tkinter, Datetime, and SQLite come as preinstalled modules in Python, there is no need to install them manually. However, we only require installing the Tkcalendar module. The tkcalendar module can be installed using the PIP installer by typing the following command in a command prompt or terminal. Syntax: Once the installation is complete, we can verify whether the tkcalendar library is installed properly or not by creating a new python program file and importing the tkcalendar module. The following is the snippet of code illustrating the same. File: verify.py Now, let us save the file and run the following command in a command prompt or terminal. Syntax: The library has been installed successfully if the program does not return any importing error. In case any exception is raised, try reinstalling the library and consider checking their official documentation. Let us now start building the project. Building the Expense Tracker using Tkinter in PythonIn order to build the Expense Tracker in Python, we will create an empty folder and name it "Expense Tracker". Within this folder, we will create a Python program file as "main.py", where we will write the entire code of the project. We have divided the complete project code for creating the Expense Tracker in Python into several steps for better understanding. These steps are shown below: Step 1: Importing the necessary modules. Step 2: Creating the database and defining functions to manipulate the data. Step 3: Connecting to the database and creating the main window of the application. Step 4: Adding necessary widgets to the window and setting the event triggers. Let us understand the steps mentioned above in a more elaborate way. Importing the necessary modulesAt first, we will start by importing all the required modules, which include all the widgets and modules from the tkinter module, the DateEntry class from the tkcalendar library, and the datetime and sqlite3 modules. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have imported all classes and modules from the tkinter module to create the GUI window and add widgets to the application. We have also imported the ttk and messagebox modules from the tkinter module to add ttk widgets and display any important messages. We have then imported the datetime module to retrieve the current date and time. We have also imported the sqlite3 module to maintain a database of the entered entries. At last, we have imported the DateEntry class of the tkcalendar module to insert the date from the drop-down calendar. Creating the Database and Defining the necessary FunctionsNow that we have imported all the necessary modules to the project, it is time to create the database and define various functions implementing different operations in the application. These functions include retrieving the data from the database and listing them in the table, viewing a record from the data table, resetting the entry fields, removing a selected record from the database, deleting all the records from the database, adding a new record to the database, updating the details of the pre-existing record in the database, and displaying the record details in text format. Let us now understand the implementation of these functions in detail. Listing all Expenses from the database to the table We will start by defining the function to list all the expenses. This function will fetch the records from the database table and insert those values iteratively in the data table we will create using Tkinter. Let us now consider the following snippet of code illustrating the same. File: main.py Explanation: In the above code snippet, we have defined the function as listAllExpenses(). Inside this function, we have used some global variables like dbconnector and data_table. We have then used the delete() method to delete the pre-existing data from the Tkinter table. We have then executed the SQL SELECT statement to retrieve the data from the database table and stored them in a variable. We have then used the fetchall() method to list the data from the table. We have then used the for-loop to iterate through the values and insert them in the table using the insert() method. Viewing an Expense Information We will now define a function to display the details of the selected expense. This function will collect the data from the different columns of the selected record and return the values in the data frame. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as viewExpenseInfo(). We have used some global variables inside this function and returned a message box displaying an error if no row is selected from the table using the showerror() method of the of the tkinter's messagebox module. We then collected the data from the selected row in dictionary format using the item() method. We have then defined another variable and stored the values from the collected data in a list. At last, we have retrieved the date from the list and set the list data in their respective entry fields in the data entry frame. Resetting the entries in the data entry frame We will now define a function to clear the user's entries in the data frame's entry fields. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as clearFields(). Within this function, we have used some global variables. We have then defined a variable to store the current date. At last, we have set the values in the entry fields back to initial and removed the specified item from the selection. Deleting the selected record from the table We will now define a function to delete the selected record from the table as well as the database. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as removeExpense(). Within this function, we have checked whether any row is selected and returned a message box displaying an error for the same using the showerror() method of the tkinter's messagebox module. We then collected the data from the selected row in dictionary format and defined another variable to store the values from the collected data. We have then used the askyesnow() method of the tkinter's messagebox module to display the message box asking for confirmation. We have then executed the SQL DELETE statement to delete the selected record. We then called the listAllExpenses() function and returned the message box that displayed the success message. Deleting all the entries from the table We will now define a function to remove all the entries from the table as well as the database. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as removeAllExpenses(). Within this function, we have displayed a message box asking for the user's confirmation with the help of the askyesno() method. We then used the delete() method to delete all the records from the table. We have also executed the SQL DELETE statement to delete all the entries from the database table. We have also called the clearFields() and listAllExpenses() functions, returning the message box displaying the information using the messagebox's showinfo() method. Adding a new record to the table We will now define a function to add a new record to the table as well as the database. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as addAnotherExpense(). Within this function, we have used some global variables. We have then returned a message box raising an error if any of the fields is empty using the showerror() method of the messagebox module. We have then executed the SQL INSERT statement to add the record to the database table. We have called the clearFields() and listAllExpenses() functions and returned the message box displaying the SUCCESS message using the messagebox's showinfo() method. Editing the details of the Selected Expense We will now define a function to edit the details of the selected expense and update the same in the table and the database. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above code snippet, we have defined the function as editExpense(). Inside this function, we have used some global variables. We have then defined a nested function as editExistingExpense(). Inside this nested function, we have again used some global variables and stored the data in the dictionary format of the selected record using the item() method. We then separated the values from the collected data, storing them in another variable and using the SQL UPDATE statement to update the selected record details in the database table. We then called the clearFields() and listAllExpenses() functions and returned the message box displaying the SUCCESS message using the messagebox's showinfo() method. Outside the nested function, we have used the messagebox's showerror() method to return the message box, raising the error if no row is selected. We then called the viewExpenseInfo() function and created a button using the Button() widget to call the editExistingExpense() function to edit the updated values of the record in the database. At last, we have set the button's position on the main window screen using the grid() method. Displaying the Details of the Selected Record in Words We will now define a function to return the message box displaying the record details in words. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above code snippet, we have defined the function as selectedExpenseToWords(). Inside this function, we have used some global variables, checked whether the row was selected or not, and returned the message box, raising an error for the same using the messagebox's showerror() method. We then used the item() method to collected the data from the selected row in the dictionary format and defined another variable to store the values from the dictionary. We have then defined the message to be displayed and returned it in the message box with the help of the showinfo() method of the messagebox module. Displaying the Expense Details in Words before Adding them to the Table We will now define the last function to display the expense details in words before inserting them into the table and the database. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have defined the function as expenseToWordsBeforeAdding(). Inside this function, we have used some global variables. We then returned a message box raising an error if any fields are empty. We have then defined the message to be displayed in the message box. This message is then printed in a message box asking for confirmation using the askyesno() method of the messagebox module to insert the details in the database table. We then called the addAnotherExpense() function and returned a message box displaying the information using the messagebox's showinfo() method. Connecting to the database and creating the main window of the applicationNow that we have defined all the necessary functions and created the database, it is time for us to connect the application to the database and create the main window of the application. First, we will connect the application to the database using different methods of the sqlite3 module. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above code snippet, we have connected the Python script to the SQLite database to store all the information. In order to connect to the database, we have created an instance as dbconnector using the sqlite3.connect(<databaseName>) method. Now that the database is created and activated, we have used the execute() and commit() methods to perform functions in the database. Thus, we have successfully established the connection to the database. We will now create a main window of the application using the Tk() class of the tkinter module. We will also set a title for the application and its size and position on the screen. We will also configure a background color and an icon. File: main.py Explanation: In the above snippet of code, we have created the main window by instantiating the Tk() class as main_win. We then used the title() method to set the title of the window. We have also set the size and position of the window using the geometry() method and disabled the resizable option for better UI by setting the values of the parameters of the resizable() method to 0. We have configured the background color of the window with the help of the config() method. At last, we have used the iconbitmap() method to set the icon of the window. Adding the necessary widgets to the window and setting the event triggersSince the main window of the application is created successfully, we will add all the necessary widgets to the window and set the event triggers. These widgets include frames to structure other widgets, labels to display important information, entry fields to insert data, and buttons to manipulate the entered data and call the functions. Let us now understand the addition of these widgets in detail. Adding Frames We will start by adding the frames to the main window. These frames will help structure the other widgets. These frames can be created using the Frame() widget of the tkinter module. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above snippet of code, we have used the Frame() widgets to add the frames to the window. We have also set the master parameters of the first two frames to main_win, indicating left and right sides of the window. We have then set the master parameters of the next three frames to frameLeft, indicating the smaller frame segments of the left frame. We have then set the master parameters of the remaining two frames to frameRight, indicating the smaller frame segments of the right frame. We have configured the background color by setting it as a value for the bg parameter. At last, we have used the pack() method to set the positions of these frames. Now that we have added the frames to the application, it is time to add the remaining widgets like labels, entry fields, an options menu, buttons, and a table to their respective frame. Adding the widgets to the frameL1 frame We will start by adding some labels to the first frame, i.e., frameL1. These labels will include the heading of the application and a subheading indicating the data entry section. We will use the Label() widget to create the required label. Let us consider the following snippet of code demonstrating the same. File: main.py Explanation: In the above code snippet, we have used the Label() widget to create the required labels. We have then set the master parameter of these labels to the frameL1 frame. We have also specified the text to be displayed, font style, background, and foreground color. At last, we have used the pack() method to set the position of the above labels. Adding the widgets to the frameL2 frame We will now add some widgets to the second frame, i.e., frameL2. These widgets include labels to display some information, entry fields, and an options menu to enter labeled data. We will use the Label() widget to create the labels, the Entry() widget to create the Entry fields, and OptionMenu() widget to create a drop-down menu. We will also use the DateEntry() widget to create a drop-down calendar for the user to enter the date. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have used the Label() widget to add some labels asking the user to enter the date, expense description, amount, payee's name, and the mode of payment to the application. We have set the master parameter of these labels to frameL2, one of the frames we defined earlier. We then used the grid() method to set the position of these labels in the grid format. We have then instantiated the StringVar() class to retrieve the data in the String format. We have also instantiated the DoubleVar() class to retrieve the amount in the double data type. We have then used the DateEntry() class to add a drop-down calendar from which the user can select the date. We have added some entry fields for the user to enter data, like the description of the expense, its amount, and the payee's name, using the Entry() widget and setting their master parameters to the frameL2 frame. We have also included a drop-down menu to select the mode of payment using the OptionMenu() widget and set its master parameter to the frameL2 frame. At last, we have used the grid() method again in order to set the position of the above widgets in the grid format on the main window screen. Adding the widgets to the frameL3 frame We will now add some buttons to the third frame, i.e., frameL3. These buttons will allow the user to add the expense to the table, convert the expense into text before adding, and reset the entry. We will use the Button() widget to create the buttons. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have used the Button() widget to add the buttons to the application. We have set the master parameter of these buttons to frameL3, one of the frames we created earlier. We have also specified their command parameters to different functions we defined earlier to manipulate the data. At last, we have used the grid() method to set the position of these buttons in the grid format. Adding the widgets to the frameR1 frame We will now add some more buttons to the fourth frame, i.e., frameR1. These buttons will allow the user to view the details of the selected expense, edit the selected expense's details, display the expense details in words, delete the selected record from the table, and delete all the records from the table. We will again use the Button() widget to create the buttons. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have used the Button() widget to add the buttons to the application. We have set the master parameter of these buttons to frameR1, one of the frames we created earlier. We have also specified their command parameters to different functions we defined earlier to manipulate the data. At last, we have used the grid() method to set the position of these buttons in the grid format. Adding the widgets to the frameR2 frame We will now add a table to the fifth frame, i.e., frameR2. This table will display all the record from the database. We will use the Treeview() widget of the ttk module to create a tabular structure for the data. We will also include horizontal and vertical scrollbars to this structure with the help of the Scrollbar() widget so that users can freely scroll to access the data. Moreover, we will also add different headings and columns to make it looks like a table. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have created a tabular structure using the Treeview() widget of the ttk module and set the master parameter of this widget to frameR2, one of the frames we defined earlier. We have also specified the selection mode and name of the columns for this widget. Later, we created two scrollbars for the table using the Scrollbar() widget, setting the master parameter of these widgets to data_table, the tabular structure we created earlier. We have also set the orientation of these scrollbars to HORIZONTAL and VERTICAL, respectively. We then used the pack() method to set the position of these scrollbars on the table. We have also used the config() method to configure these scrollbars on the table. After that, we added different headings and columns to the table. At last, we have used the place() method to set the position of the table on the main window screen. Running the Application We will use the mainloop() method with the object of the Tk() class to run the application. Let us consider the following snippet of code illustrating the same. File: main.py Explanation: In the above snippet of code, we have used the mainloop() method with main_win, the object of the Tk() class, to run the application. Hence, the project code is now complete. We will save this python program file and run the following command in the command prompt or terminal to see the output. Syntax: But before we see the output, the complete project code of the 'Expense Tracker Application using Tkinter' is shown below. The Complete Project CodeThe following is the project code for the 'Expense Tracker Application using Tkinter in Python'. File: main.py Output: Next TopicVariable Scope in Python |