Developing a Memo App with Tkinter (2) - Saving a Memo to a Text File
Continuing from the previous “Hello World” program, this session dives into building a memo app with the following functionalities:
- A text box for entering a memo.
- A shortcut (
Control+S
) for saving the contents of the text box to a file. - Displaying the file contents in the text box upon app launch.
1. Setting Up the Text Box
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()
...
2. Saving Data with Control+S
Next, we’ll configure the app so that pressing Control+S
saves the text box’s contents to a file.
2.1. Retrieving Text from the Widget
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")
2.2. Setting Up Key Bindings
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>)
2.3. Defining the Save Function
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)
2.4. Testing the Setup
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.
3. Loading File Content at Startup
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()
Conclusion
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.