Entry widget in CustomTkinter: Build your own learning diary

Hello, Pythonistas🙋‍♀️ welcome back. After exploring how to customize your GUI in CustomTkinter in the previous post, today we are gonna deep dive🏊‍♀️ into the entry widget in CustomTkinter.

We will be creating a simple basic learning diary📒 app to understand the entry widget in CustomTkinter.

The application would have a straightforward functionality where users can input their daily 📚 learning and save it along with the current date.

So let’s get straight into it…

Final output

Previous post’s challenge’s solution

Here’s the solution 🧪 to the challenge provided in the last post:

# Importing the CustomTkinter library and the random module
from customtkinter import *
import random
# Defining a class named App which inherits from CTk class
class App(CTk):
    # Constructor method which initializes the instance variables
    def __init__(self):
        # Calling the constructor of the parent class
        super().__init__()
        # Generating a random number between 1 and 10 and storing it in an instance variable 'num'
        self.num = random.randint(1, 10)
        # Creating a label widget with the text of the random number
        self.label = CTkLabel(self, text=f"{self.num}")
        # Packing the label widget onto the window
        self.label.pack()
# Checking if the current module is the main module
if __name__ == "__main__":
    # Creating an instance of the App class
    app = App()
    # Starting the main event loop
    app.mainloop()

Please read the comments in the code to understand it clearly.👍

If you still have any doubts ask them in the comment section below.👇

Introduction to the entry widget: How to take text from the user

The Entry widget is a standard GUI widget used in GUI programming to allow users to enter single-line text input.

It provides a rectangular box in which the user can type or paste text, and the text is displayed on the screen as the user types.

The user can also edit the text, delete characters, and move the cursor to any position in the text.

Let’s understand this well with an example…

To make our Learning 📒 diary, we first need to let the user type in the text.

We will use the entry widget of CustomTkinter for this purpose.

Here’s how to do it:

from customtkinter import *
class App(CTk):
    def __init__(self):
        super().__init__()
        self.text = CTkEntry(self, placeholder_text="how was your day?...")
        self.text.pack(padx=20, pady=20)
if __name__ == "__main__":
    app = App()
    app.mainloop()

Just as you do with any other widget in CTk we:

  • first need to make the widget and
  • then need to display it on the window.

Here, the self is the master of the widget, which means the widget will be displayed on our object(window).

The second argument placeholder_text is like the prompt of the input function in python. This tells the user what needs to be entered in the text box.

Output:

entry widget in CTk

I am using OOP as, Writing a lot of UI code without classes, and in single .py file with global variables like it’s often done is a pain to read and very bad coding style!

The show attribute: Dealing with sensitive🤫 information

Now this is a simple diary, so we don’t need anything like passwords to protect it.

But, what if it was an important text like passwords? Then, no one should know the details.

So, to let the users type in passwords and other sensitive🤫 details safely we can use the show attribute:

from customtkinter import *
class App(CTk):
    def __init__(self):
        super().__init__()
        self.text = CTkEntry(self, placeholder_text="Password please!...", show="*")
        self.text.pack(padx=20, pady=20)
if __name__ == "__main__":
    app = App()
    app.mainloop()

Output:

input password in CTk entry widget

Here whatever you type in would be displayed as "*"

get() method: how to use that text in python

The user will be able to type in the text this way. But, how on earth🌏 will you be able to save💾 this to a file without accessing that text?

So, to access this value we will use the get() method:

from customtkinter import *
class App(CTk):
    def __init__(self):
        super().__init__()
        self.text = CTkEntry(self, placeholder_text="What did you learn today...")
        self.text.pack(padx=20, pady=20)
        self.b = CTkButton(self, text="Print this", command=self.clicked).pack(padx=20, pady=20)
    def clicked(self):
        print(self.text.get())
if __name__ == "__main__":
    app = App()
    app.mainloop()

Here we created a button🟪 that will simply print the text we typed in the Entry widget.

Easy right✔?

There’s another way to do it too…

Using Tkinter’s StringVar

StringVar is a class of the Tkinter library that represents a mutable(changeable) string variable.

It can be used to: set and get the value of a Tkinter widget such as an Entry, Label, or Button widget.

When a StringVar object is associated with a widget, any changes made to the object will be reflected in the widget and vice versa. This makes it easy to synchronize the values of different widgets and update them dynamically.

StringVar can also be used to set default values and as a placeholder text in widgets like Entry and Text widgets.

Additionally, it can be used to set up a trace on the variable so that any changes to it can be monitored and acted upon as needed.

I know you are quite confused🥴 so let’s see it with an example.

We are going to save this text in a file right?

So we might want our entry widget to display "Saving your day's learning📚...". This would let the user know that his/her text will be saved.

from customtkinter import *
class App(CTk):
    def __init__(self):
        super().__init__()
        self.var = StringVar()  # create a StringVar object
        self.text = CTkEntry(self, textvariable=self.var, placeholder_text="What did you learn today...")
        self.text.pack(padx=20, pady=20)
        self.b = CTkButton(self, text="Print this", command=self.clicked)
        self.b.pack(padx=20, pady=20)
    def clicked(self):
        text = self.var.get()  # retrieve the text from the StringVar object
        self.var.set("Saving your day's learning...")
        print(text)
if __name__ == "__main__":
    app = App()
    app.mainloop()

To use this way you:

  • first need to create a StringVar class’s object.
  • Then you need to connect it with the entry widget using the textvariable attribute.
  • Now, you can get and set the text in the entry widget as and when needed.

Note: the placeholder_text would show no effects as, it is an attribute of CTk, not Tk, and StringVar is of Tk.

However, you can give a placeholder using the insert method:

self.text.insert(0,"What did you learn today...")

But, I wouldn’t be using this method in this app.

saving that text to our file

Unfortunately😞, CTk doesn’t provide a way to open the file dialog box to save files. But, fortunately😀👍, we have asksaveasfilename of Tkinter’s filedialog.

Let’s first understand what is asksaveasfilename.

This is a function provided by tkinter.filedialog module in Python.

It opens a dialog box that allows the user to choose ☝a file name and ✌location to save a file. It returns the full path of the selected file as a string.

This way we can ☝first create and ✌save our file and ✌☝then can write in it the text we got from the entry widget.

To use this we first need to import asksaveasfilename from tkinter.filedialog:

from tkinter.filedialog import asksaveasfilename

Now, we will:

  • First, create and save the file using asksaveasfilename
  • And using the file path it returns we will write the text from the entry widget in the file.
def save_file(self):
        file_path = asksaveasfilename()
        if file_path:
            with open(file_path, 'w') as file:
                file.write(self.text.get())

Finally, you just need to link this function to the button. That’s it.

Note: There are a lot of other features that the filedialog of Tkinter provides, also asksaveasfilename has a lot of attributes, we will cover them in the later articles.

Putting pieces🧩 together: the making of our learning diary

For this, we will need to give an icon to our app first. I took it from here. And yes you would need a .ico file.

To change the icon of the app:

self.iconbitmap("icon.ico")
#To set title
self.title("Learnify")

Now, we will resize our window:

self.geometry("250x150")

Let’s increase the size of the entry widget:

self.text = CTkEntry(self, placeholder_text="What did you learn today...")
self.text.configure(width=300, height=50)
self.text.pack(padx=20, pady=20)

Let’s change the text of the button and also change the button’s style:

self.b = CTkButton(self, text="Save Day's Learning", command=self.save_file)
self.b.configure(fg_color="#63FF7C", hover_color="#ff63e6", text_color="#060156", font=("Calibri Bold Italic",16))
self.b.pack(padx=20, pady=20)

We would also write the current date in the file before saving the learning. For this let’s modify the save_file() method: (Also import the datetime module)

def save_file(self):
        file_path = asksaveasfilename()
        if file_path:
            with open(file_path, 'w') as file:
                file.write(f"{datetime.datetime.now().strftime('%d-%m-%Y')}\n{self.text.get()}")

datetime.datetime.now().strftime('%d-%m-%Y') this will give us the current date and self.text.get() this will give us the learning by the user.

Both will be written in the file in separate lines.

And that’s it our Leanify📚 app is ready.

Customizing the entry widget

You can customize fg_color, width, height, corner_radius, text_color, placeholder_text_color, placeholder_text, font, state, etc… of the entry widget.

You can customize it this way:

self.text.configure(width=200, height=10, fg_color="", placeholder_text="", placeholder_text_color="", font="", state="")

Full Code:

from customtkinter import *
from tkinter.filedialog import asksaveasfilename
import datetime
class App(CTk):
    def __init__(self):
        super().__init__()
        self.iconbitmap("icon.ico")
        self.title("Learnify")
        self.geometry("300x200")
        self.text = CTkEntry(self, placeholder_text="What did you learn today...")
        self.text.configure(width=300, height=50)
        self.text.pack(padx=20, pady=20)
        self.b = CTkButton(self, text="Save Day's Learning", command=self.save_file)
        self.b.configure(fg_color="#63FF7C", hover_color="#ff63e6", text_color="#060156", font=("Calibri Bold Italic",16))
        self.b.pack(padx=20, pady=20)
    def save_file(self):
        file_path = asksaveasfilename()
        if file_path:
            with open(file_path, 'w') as file:
                file.write(f"{datetime.datetime.now().strftime('%d-%m-%Y')}\n{self.text.get()}")
if __name__ == "__main__":
    app = App()
    app.mainloop()

Conclusion

Ok so now we come to the end of this post. You can go on optimizing⚙️ the app further adding more features✨ and functionalities✨.

Here in we discussed what is an Entry widget how to make and use one in CTk. We saw some important attributes and methods related to them.

Also, we saw how to use a file dialog box using Tkinter. Throughout the process, we made pieces🧩 of our Learnify📚 app.

In the end, we created our app putting these pieces together.

We also saw how you can add customizations to the Entry widget.

Challenge 🧗‍♀️

Your challenge for this post is to create a simple login form that takes up a username and password.

  • If they match it should display:
    • “Welcome to the learning diary”
  • if not then,
    • “Incorrect username or password(whichever is the case)”.

Happy solving…

Stay happy 😄 and keep coding and do suggest any improvements if there. Take care and have a great 😊 time I’ll see you soon in the next post…Bye Bye👋

Leave a Reply

This Post Has 2 Comments

  1. novo

    This question is not clear to me.

  2. Maitry

    Are you talking about the challenge question? Can you be specific about what are you not clear with?