Open In App

Disappearing Text Desktop Application in Python

Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will build an exciting desktop application using Python and its GUI library, Tkinter.

Disappearing Text Desktop Application in Python

The app is simple to use. The user will start writing whatever he wants to write. If he takes a pause for 5 seconds, the text he has written is deleted. The user can even save his text in a text file, although, he will need to click on the save button within 5 seconds after he stops typing. This app can be used to practice typing fast, and not taking long pauses.

File Structure:

Disappearing Text App using Python

 

Step 1: The UI Setup

When building an application such as this, we divide our concerns. We handle the UI part and the logic part separately. First, we will tackle the UI part. We import everything from the Tkinter library. Then we use its Tk() class to create a window object. This object is the window in which our program is seen. We call its mainloop() method and place it at the last line of our code. This method keeps the screen of our window open, otherwise, the window will open and close within a second. Remember that no matter what we do to the code, window.mainloop() will always remain on the last line of the code

Then we create some constants to store color codes, integers that will serve as font size, string values that will serve as font style, and some more string values that will serve as a font family. We use all these constants to create fonts that we will use to show text elements of our UI. You can choose to use a single font for your entire code if you want to.

Next, we create our widgets. We use Label() class to create text elements, Button() class to create a button, and the Text() class to create a typing area. While creating objects from these classes, we pass it various arguments that manipulate the look of that widget, such as text to give the text to our widget, fg, and bg for setting foreground color and background colors respectively, and font to set the font of our widget, some properties to set or remove boundaries of our widgets, and lastly, the command argument takes the name of a method. This argument is given to buttons so that when we click on them, a method is called, which is the feature of this command,

Use the bind method on the typing area widget so that each time the user hits a key on the keyboard, a method is called. The method called here will calculate the time user takes between each keystroke and deletes the text typed by him if he took 5 seconds.

The last thing to do is to place our widgets on the window. We use the grid layout for this, which is nothing but a 2D layout of rows and columns. The first row and the first column are given an index of zero, the second one is given an index of one, and so on. Just like list indexing. Call the grid() method on each widget, and give it row, column, and spanning values. You can play with the UI as much as your want and make it to your liking.

Python3




# UI SETUP - Whatever the user sees is handled here
 
# create constants that simply containers color codes,
# font family, sizes and styles
 
# COLORS
BORDER = "#3C2C3E"
FG = 'khaki'
BG = "#4B5D67"
 
# FONT FAMILIES
FONT_FAMILY1 = 'Calibri'
FONT_FAMILY2 = 'Helvetica'
 
 
# FONT SIZES
FONT_SIZE1 = 14
FONT_SIZE2 = 18
FONT_SIZE3 = 24
 
 
# FONT STYLES
FONT_STYLE1 = 'normal'
FONT_STYLE2 = 'italic'
FONT_STYLE3 = 'bold'
 
# creating a font from family, style and size for the UI
PARA_FONT = (FONT_FAMILY1, FONT_SIZE1, FONT_STYLE3)
PARA_FONT2 = (FONT_FAMILY1, 12, FONT_STYLE2)
HEAD_FONT = (FONT_FAMILY2, FONT_SIZE3, FONT_STYLE1)
 
# welcoming heading of our UI
heading = "WRITE WITH MAGICAL INK"
# instruction to use app
instruction = "If you don't press any key for 5 seconds,\
the text you have written will disappear"
 
 
# CREATING THE WINDOW IN WHICH OUR PROGRAM IS SEEN.
 
"""
1. Creating an window object in which our program
is seen using Tk class.
2. Give it a title that shows on the window's tab
using title method on window object.
3. Use config method of window object to set various
other properties: background color,
padding on x-axis and padding on y-axis. Padding
is simply the empty space between
contents and boundary of the window in
which our program is viewed.
"""
window = Tk()
window.title('Disappearing Text Desktop App')
window.config(bg=BG, padx=20, pady=10)
 
 
# CREATING WIDGETS FOR OUR APPLICATION
 
# heading.
heading = Label(text=heading, font=HEAD_FONT,
                bg=BG, fg=FG, padx=10, pady=10)
 
# instructions.
instruction = Label(text=instruction, font=PARA_FONT2,
                    fg=FG, bg=BG, pady=10)
 
# typing area in which user types his text.
typing_area = Text(font=PARA_FONT, bg=BG, fg=FG,
                   width=100, height=15, wrap='w',
                   highlightcolor=BORDER,
                   highlightthickness=4,
                   highlightbackground=BORDER,
                   padx=5, pady=5)
 
# attaching a function to text area. This function
# does main calculations for the app.
typing_area.bind('<KeyPress>', start_calculating)
 
# a reset button so that user can explicitly reset
# the application if he wants to.
reset_btn = Button(text='Reset', fg=FG, bg=BG, font=PARA_FONT,
                   highlightbackground=FG,
                   highlightcolor=FG,
                   highlightthickness=0, border=3,
                   command=reset_app, width=50)
 
 
# a save button for user to save his text in a text file
save_btn = Button(text='Save', fg=FG, bg=BG,
                  font=PARA_FONT,
                  highlightbackground=FG,
                  highlightcolor=FG, highlightthickness=0,
                  border=3,
                  command=save_text, width=50)
 
 
# PLACING THE WIDGETS ON THE WINDOW
heading.grid(row=0, column=0, columnspan=3)
instruction.grid(row=2, column=0, columnspan=3)
typing_area.grid(row=3, column=0, columnspan=3)
reset_btn.grid(row=4, column=0)
save_btn.grid(row=4, column=2)
 
"""we keep the window open, until closed
explicity by user using
mainloop method of window object."""
window.mainloop()


Step 2: Tracking User-Typed Text

First, we create two global variables, user_text to store the user-typed text. We are going to need it in case the user wants to save his text in a file. The saving functionality will be handled by a separate function, thus this variable needs to be kept global for other methods to use it. The next global variable we create is the timer variable. This will store the value returned by the window.after() method. This timer will be passed to the window.after_cancel() method to cancel the timer. 

What is the timer here? window.after() method takes two arguments, time in milliseconds and a method. After the specified amount of time is passed, the method that was passed to it is called. In order to cancel this timer, we use window.after_cancel() method, which takes a single argument, the timer returned by the window.after() method.

Since we want to call the reset method, which deletes the text after 5 seconds, the first argument of the window.after() method is 5000 and reset_app is the second argument. Do not type the parenthesis with the method’s name, since we don’t want the method to be called when the interpreter encounters the line on which this piece of code is written, and only when this specific event occurs. The first line of the function definition of the start_calculating method simply tells the function to use the global variables, then we check if the timer is defined or None. If it is None. we cancel it using after_cancel() method.  The start_calculating method automatically takes the event argument, which tells us the information about the keypress. If the user pressed BackSpace, we use string slicing to remove the last character from the user_text string, otherwise, just append this new character to the user_text string. Then, we call the window.after(5000, reset_app) method to reset the app after 5 seconds, and store its returned value in the global variable, timer. 

Why did we cancel the timer in the beginning?  The start_calculating method is called every time the user presses a key, The first time user pressed a key, the timer was still None, but after the key was pressed and the key appended to user_text, the timer was created. After 5 seconds it would call the reset method that deletes the user-typed text. But the fact that this method was called again, means the user typed another key before 5 seconds elapsed, thus we cancel the timer, and prevent the text from being deleted. But if he took 5 seconds, then that means this method was not called, the timer could not be canceled, and thus the reset_app method was called and the user’s text was deleted.

At last, we return the method to get out of the method. Since all of the function’s lines were executed, the function will automatically end, but it is a good practice to use the return keyword to make sure that the program got out of the function.

Python3




from tkinter import *
 
# LOGIC
 
user_text = ""
timer = None
 
# method to do the main calculations
def start_calculating(event):
    # global keyword tells the function to use the following identifiers
    # are variables outside this function.
    global timer, user_text
 
    if timer is not None:
        window.after_cancel(timer)
     
    # keysym property of event simply tell us which key was pressed
    if event.keysym == "BackSpace":
        user_text = user_text[0: len(user_text) - 1]
         
    # we access the character of the key using char property.
    elif event.char:
        user_text += event.char
        timer = window.after(5000, reset_app)
 
    return


Step3: The Reset Function

We call the delete method on typing_area to delete user-typed text. It takes two arguments, starting value and end value. It means that this method deletes a portion of the text, since we want to delete the entire text, the starting value is 1.0 which means the first character and end keyword as the ending value. Then we set the timer variable back to none, and the user_text variable back to an empty string. The user can also explicitly reset the app by clicking on the reset button. We he does that, the reset_app method will be called since we provided its name as the value for the command argument. Then, we return the function.

Python3




def reset_app():
        # get the global variable timer and set it to None again.
    global timer, user_text
 
    # delete the text typed in typing area, using delete method.
    # 1.0 is the starting index, i.e., the first character and end means
    # delete all character till last character.
    typing_area.delete('1.0', 'end')
    user_text = ""
    timer = None
    return


Step 4: The Save Function

We access the user’s text, if it is empty, i.e., the user clicked the save button without typing anything, we do nothing and return. If not, we open a text file and write the user’s text to it if the file did not exist, otherwise, if the file already exists, we append to it only if the file was not empty, else, we write to it. We nest the reading, writing, and appending of files in the try, except, and else blocks to handle errors. try block takes the code that might return an error. except block executes a piece of code if the error was generated. If no error was generated, else block is executed. We can add keywords to except so that we run the code only on a specific error. Here, the only error we care about is ‘the file not found error’, thus we add the keyword, FileNotFoundError. Once we are done with the error handling in the else block, we return the function, using the return keyword in the final block. It executes whether the error was found or not.

Python3




def save_text():
    global user_text
    if user_text == "":
        return
    try:
        f = open('writeups.txt', 'r')
    except FileNotFoundError:
        f = open('writeups.txt', 'w')
        f.write(user_text)
        user_text = ""
        return
    else:
        cont = f.read()
        if cont == "":
            text_to_write = user_text
        else:
            text_to_write = f'\n{user_text}'
 
        with open('writeups.txt', 'a') as f:
            f.write(text_to_write)
            user_text = ""
        finally:
        return


Complete Code:

Python3




from tkinter import *
 
# LOGIC
user_text = ""
timer = None
 
 
def start_calculating(event):
    global timer, user_text
 
    if timer is not None:
        window.after_cancel(timer)
 
    if event.keysym == "BackSpace":
        user_text = user_text[0: len(user_text) - 1]
 
    elif event.char:
        user_text += event.char
        timer = window.after(5000, reset_app)
 
    return
 
 
def reset_app():
    global timer, user_text
    typing_area.delete('1.0', 'end')
    user_text = ""
    timer = None
    return
 
 
def save_text():
    global user_text
    if user_text == "":
        return
    try:
        f = open('writeups.txt', 'r')
    except FileNotFoundError:
        f = open('writeups.txt', 'w')
        f.write(user_text)
        user_text = ""
        return
    else:
        cont = f.read()
        if cont == "":
            text_to_write = user_text
        else:
            text_to_write = f'\n{user_text}'
 
        with open('writeups.txt', 'a') as f:
            f.write(text_to_write)
            user_text = ""
    finally:
        return
 
 
# UI SETUP
 
BORDER = "#3C2C3E"
FG = 'khaki'
BG = "#4B5D67"
 
FONT_FAMILY1 = 'Calibri'
FONT_FAMILY2 = 'Helvetica'
 
FONT_SIZE1 = 14
FONT_SIZE2 = 18
FONT_SIZE3 = 24
 
FONT_STYLE1 = 'normal'
FONT_STYLE2 = 'italic'
FONT_STYLE3 = 'bold'
 
PARA_FONT = (FONT_FAMILY1, FONT_SIZE1, FONT_STYLE3)
PARA_FONT2 = (FONT_FAMILY1, 12, FONT_STYLE2)
HEAD_FONT = (FONT_FAMILY2, FONT_SIZE3, FONT_STYLE1)
 
heading = "WRITE WITH MAGICAL INK"
instruction = "If you don't press any key for 5 seconds, \
the text you have written will disappear"
 
window = Tk()
window.title('Disappearing Text Desktop App')
window.config(bg=BG, padx=20, pady=10)
 
heading = Label(text=heading, font=HEAD_FONT,
                bg=BG, fg=FG, padx=10, pady=10)
instruction = Label(text=instruction, font=PARA_FONT2,
                    fg=FG, bg=BG, pady=10)
typing_area = Text(font=PARA_FONT, bg=BG, fg=FG,
                   width=100, height=15, wrap='w',
                   highlightcolor=BORDER,
                   highlightthickness=4,
                   highlightbackground=BORDER,
                   padx=5, pady=5)
typing_area.bind('<KeyPress>', start_calculating)
reset_btn = Button(text='Reset', fg=FG, bg=BG,
                   font=PARA_FONT,
                   highlightbackground=FG,
                   highlightcolor=FG,
                   highlightthickness=0, border=3,
                   command=reset_app, width=50)
 
save_btn = Button(text='Save', fg=FG, bg=BG,
                  font=PARA_FONT,
                   highlightbackground=FG,
                  highlightcolor=FG,
                  highlightthickness=0, border=3,
                  command=save_text, width=50)
 
heading.grid(row=0, column=0, columnspan=3)
instruction.grid(row=2, column=0, columnspan=3)
typing_area.grid(row=3, column=0, columnspan=3)
reset_btn.grid(row=4, column=0)
save_btn.grid(row=4, column=2)
 
 
window.mainloop()


Output:

Disappearing Text App using Python

Code Output



Last Updated : 27 Jul, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads