Developing a Memo App with Tkinter (2) - Saving a Memo to a Text File

Series - Developing a Memo App with Tkinter

Continuing from the previous “Hello World” program, this session dives into building a memo app with the following functionalities:

  1. A text box for entering a memo.
  2. A shortcut (Control+S) for saving the contents of the text box to a file.
  3. Displaying the file contents in the text box upon app launch.

Let’s get started by building on our previous program. First, we create the root window and place a frame inside it. Within this frame, we’ll set up the text box for memo entry.

In Tkinter, there are mainly two widgets for entering text: the Entry widget for single-line input and the Text widget for multi-line input. Given our needs, we’ll use the Text widget.

from tkinter import Tk, Text
from tkinter import ttk

# Create the root window
root = Tk()

# Place a frame with padding
frm = ttk.Frame(root, padding=10)
frm.grid()

# Place a text box inside the frame
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

# Run the main loop
root.mainloop()

When you run the above code, a window like the one shown below appears:

Setting the frame’s padding=10 specifies the margin size between it and the root window.
Let’s see how it looks with a little less padding.

...
# Place a frame with padding
frm = ttk.Frame(root, padding=5)
frm.grid()
...

Next, we’ll configure the app so that pressing Control+S saves the text box’s contents to a file.

To get the text from our widget, we use the get method:

text_widget.get(<start position>, <end position>)

You specify the position using the format "<line number>.<character index>".
For instance, to reference the first character, you would use "1.0" (the 0th character of the first line).
To specify the end of the text, you use "end".

To capture all text:

text = text_widget.get("1.0", "end")

We use the widget’s bind method to set up key bindings.
Here, we want Control+s to trigger saving from anywhere within the app, so we set it up on the root:

# Bind Control+S to save the text
root.bind('<Control-s>', <function to execute>)

Finally, we define a function that saves the text to a file:

from pathlib import Path

# Define the path to the memo file
MEMO_FILE = Path(__file__).parent / "memo.txt"

def save_text(event=None):
    """Save the contents of text_widget to a file."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

Run the following updated code to test the new functionalities:

from tkinter import Tk, Text
from tkinter import ttk
from pathlib import Path


# Define the path to the memo file
MEMO_FILE = Path(__file__).parent / "memo.txt"

# Create the root window
root = Tk()

# Place a frame with padding
frm = ttk.Frame(root, padding=5)
frm.grid()

# Place a text box inside the frame
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

def save_text(event=None):
    """Save the contents of text_widget to a file."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

# Bind Control+S to save the text
root.bind('<Control-s>', save_text)

# Run the main loop
root.mainloop()

Entering text and pressing Control+S should create a memo.txt file in the same directory as the script, containing the data you entered.

Finally, we’ll set up the app to display the contents of the memo file in the text widget when it launches. We use the insert method to add text to the text widget.

def load_text():
    """Load the file content into the text box at startup."""
    if MEMO_FILE.exists():
        with open(MEMO_FILE, "r") as f:
            text = f.read()
            text_widget.insert("1.0", text)  # Insert text at the starting position

We’ll ensure this function is executed before the main loop starts.
Here is the final code:

from tkinter import Tk, Text
from tkinter import ttk
from pathlib import Path

# File to save the memo (created in the same directory as the script)
MEMO_FILE = Path(__file__).parent / "memo.txt"

# Create the root window
root = Tk()

# Place a frame
frm = ttk.Frame(root, padding=5)
frm.grid()

# Place a text box inside the frame
text_widget = Text(frm)
text_widget.grid(column=0, row=0)

def load_text():
    """Load the file content into the text box at startup."""
    if MEMO_FILE.exists():
        with open(MEMO_FILE, "r") as f:
            text = f.read()
            text_widget.insert("1.0", text)

def save_text(event=None):
    """Save the content of the text widget to a file."""
    text = text_widget.get("1.0", "end")
    with open(MEMO_FILE, "w") as f:
        f.write(text)

# Bind Control+S to save the text
root.bind('<Control-s>', save_text)

# Initialize the content of the text widget
load_text()

# Run the main loop
root.mainloop()

In this session, we created a simple memo app that features a text box for data entry and saves this input to a file. Next time, we will enhance the app to allow for the creation and viewing of multiple memos.

Related Content