Build a QR Code Generator in Python
Build a desktop app that generates and saves QR codes from any text or URL.
Introduction
30 Second Summary
QR codes are everywhere. Restaurant menus, event tickets, payment apps, Wi-Fi logins. They turn any text or URL into a scannable image that works instantly.
In this project, you will build a desktop application that generates QR codes from any text or URL you type in. You'll create a graphical interface with Python that lets you preview and save QR codes as image files.
What You'll Build
A Python desktop application with a Tkinter GUI that generates, previews, and saves QR codes as PNG files from user input.
By the end of this project, you'll have:
- A working desktop application with a text input field, a generate button, and a live QR code preview inside the window.
- Hands-on experience integrating the qrcode library with Tkinter for real-time image display using Pillow.
- A saved PNG file of a custom QR code generated from your own input, saved using a native file dialog.
- Secret Mission: Add custom color options so you can generate QR codes with personalized foreground and background colors.
Are there any prerequisites?
You should have basic Python knowledge, including variables, functions, and imports. No prior experience with GUI programming or QR codes is needed.
Before We Start
You're about to build a desktop application that turns any text or URL into a scannable QR code. The app will feature a graphical interface where you type your input, click a button, and see the generated QR code instantly.
Before writing any code, you need three things on your machine: Python (the language), the qrcode library (the engine that creates QR codes), and Tkinter (the toolkit for building the graphical window).
In this step, get ready to:
- Verify Python 3.9+ is installed on your machine.
- Install the qrcode and Pillow packages.
- Confirm tkinter is available.
Verify Python is installed
This project requires Python 3.9 or higher. Let's check what version you have.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or Command Prompt (Windows) and press Enter to open it.
- Check your Python version by running this command:
python3 --version
✔️ I see version 3.9 or higher
You should see something like Python 3.11.6 or Python 3.12.4. Any version at 3.9 or above works perfectly.
Python is ready. Move on to the next substep.
ⓧ I see an older version
If you see a version below 3.9 (like 3.8.x or 3.7.x), you need to install a newer version.
- Visit python.org/downloads and download the latest Python 3 installer for your operating system.
- Run the installer. On Windows, make sure to check Add Python to PATH during installation.
- Close and reopen your terminal after installation.
- Run python3 --version again to confirm the new version appears.
macOS users with an older default Python
macOS sometimes ships with an older Python or may resolve python3 to a version you did not install. After installing from python.org, try running python3.11 --version or python3.12 --version to use the specific version you just installed.
ⓧ Command not found
Python is not installed on your machine yet.
- Visit python.org/downloads and download the latest Python 3 installer for your operating system.
- Run the installer. On Windows, make sure to check Add Python to PATH during installation.
- Close and reopen your terminal after installation.
- Run python3 --version again to confirm it now shows a version number at 3.9 or above.
Windows users
On Windows, the command may be python --version (without the 3) depending on how you installed it. If python3 doesn't work but python does, use python for all commands in this project.
Install the required packages
The qrcode library handles all the QR code encoding logic. Installing it with the [pil] extra automatically pulls in Pillow, the image processing library you'll need to display QR codes in the window.
- Install both packages in one command by running:
pip install "qrcode[pil]"
What does this command do?
The qrcode[pil] syntax tells pip to install the qrcode package along with its optional Pillow dependency. Pillow is what lets the library generate actual image files instead of just text-based QR codes.
- Verify the installation succeeded by running:
python3 -c "import qrcode; print(qrcode.__version__)"
✔️ I see a version number
You should see 8.2 (or a similar version number) printed in your terminal. The package is installed and ready to use.
ⓧ I see an error
If you see an error like ModuleNotFoundError, the package did not install correctly.
- Try running pip3 install "qrcode[pil]" instead (using pip3 instead of pip).
- On some systems, you may need python3 -m pip install "qrcode[pil]" to ensure you're installing for the correct Python version.
- Run the verification command again after reinstalling.
pip command not found?
If your terminal says pip is not recognized, try using python3 -m pip install "qrcode[pil]" instead. This calls pip through your Python installation directly.
Help me fix my pip installation
Verify tkinter is available
Tkinter is Python's built-in toolkit for creating graphical user interfaces. It comes bundled with most Python installations, so you likely already have it.
- Confirm tkinter is available by running:
python3 -c "import tkinter; print(tkinter.TkVersion)"
✔️ I see a version number
You should see a number like 8.6 printed in your terminal. Tkinter is ready to use.
ⓧ ModuleNotFoundError
This typically happens on Linux systems where tkinter is packaged separately.
- On Ubuntu or Debian-based systems, install tkinter by running:
sudo apt install python3-tk
- After installing, run the verification command again to confirm it now prints a version number.
macOS and Windows users
If you installed Python from python.org, tkinter is always included. If you see this error on macOS or Windows, it likely means your Python installation is incomplete. Reinstalling Python from python.org/downloads will fix the issue.
Still getting errors?
Make sure you're using the same python3 command that showed version 3.9+ earlier. If you have multiple Python versions installed, pip might install packages for a different version than the one running your scripts.
Help me troubleshoot my Python and tkinter setup
Your environment is ready. Next up, you'll create the application window and lay out the interface for your QR code generator.
Set Up Your Environment
Before you can build the QR code generator, you need three things on your machine: Python itself, the qrcode library for generating QR codes, and Tkinter for creating the graphical interface.
In this step, you will verify each tool is ready to go. Once everything checks out, you can jump straight into building the app.
In this step, get ready to:
- Verify Python 3.9+ is installed.
- Install the qrcode and Pillow libraries.
- Confirm tkinter is available on your system.
Verify Python is installed
Python is the programming language you will use for the entire project. You need version 3.9 or higher because that is what the qrcode library requires.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Check your Python version by running this command:
python3 --version
✔️ I see version 3.9 or higher
You should see output like Python 3.11.4 or any version at 3.9 or above. You are good to go.
ⓧ I see an older version
If you see a version below 3.9 (like 3.7 or 3.8), you need to upgrade.
- Visit python.org/downloads and download the latest Python installer for your operating system.
- Run the installer. On Windows, make sure to check Add Python to PATH before clicking Install Now.
- Close and reopen your terminal, then run python3 --version again to confirm the new version.
macOS showing an older version?
macOS sometimes ships with an older system Python. After installing a newer version from python.org, you may need to use python3.11 or python3.12 directly if python3 still resolves to the older version.
ⓧ Command not found
Python is not installed on your machine yet.
- Visit python.org/downloads and download the latest Python installer.
- Run the installer. On Windows, check Add Python to PATH before clicking Install Now.
- Close and reopen your terminal after installation finishes.
- Run python3 --version to confirm. You should see 3.9 or higher.
Windows users
On Windows, the command is often python --version (without the 3) depending on how Python was installed. Try both if one does not work.
Install the required packages
Your QR code generator depends on two libraries: qrcode for the encoding logic and Pillow for image handling. You can install both in one command.
- Install the qrcode library with its Pillow dependency by running this command:
pip install "qrcode[pil]"
What does this command do?
The [pil] part is called an "extra". It tells pip to install Pillow alongside the qrcode library. Pillow is needed to generate QR code images and to display them inside the Tkinter window later.
- Verify the installation was successful by running:
python3 -c "import qrcode; print(qrcode.__version__)"
You should see 8.2 (or a similar recent version number) printed in the terminal.
Seeing a permission error or command not found?
- If you see a permission error, try pip install --user "qrcode[pil]" to install into your user directory instead.
- If pip is not found, try pip3 instead. Some systems use pip3 for Python 3 packages.
- On Windows, if neither works, try python -m pip install "qrcode[pil]".
Help me troubleshoot my pip install for the qrcode library.
Verify tkinter is available
Tkinter is Python's built-in GUI framework. It ships with most Python installations, so you likely already have it. Let's confirm.
- Check that tkinter is available by running:
python3 -c "import tkinter; print(tkinter.TkVersion)"
You should see a version number like 8.6 printed. This confirms tkinter is ready.
Getting a ModuleNotFoundError?
On some Linux distributions, tkinter is not bundled by default. Install it with your package manager:
sudo apt install python3-tk
After the installation completes, run the import tkinter command again to confirm it works. On macOS and Windows, tkinter is always included with the standard Python installer.
Help me fix my tkinter installation issue.
Why Tkinter for this project?
Tkinter ships with Python on almost every platform. You do not need to install a separate GUI framework, which means zero extra setup. For a quick desktop tool like a QR code generator, Tkinter is the fastest path from code to a working window.
Your environment is ready. Next up, you will create the application window and lay out the GUI elements.
Create the Application Window
Your environment is ready with Python and the qrcode library installed. Now it's time to build the graphical interface your users will interact with.
Every desktop application needs a window to live in. In this step, you'll create the application window using Tkinter and add the input field, buttons, and display area that make up your QR code generator's layout.
In this step, get ready to:
- Create the application file and set up the main window.
- Add the Generate button, Save button, and image display area.
- Run the application to verify the window appears.
Create the file and set up the main window
Your application needs a Python file to hold all the GUI code. You'll structure it as a class so that all the window elements and logic stay organized together.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code and press Enter to open it.
- Create a new file by pressing Cmd+N (macOS) or Ctrl+N (Windows).
- Save the file to your Desktop as qr_generator.py by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Paste the following code into qr_generator.py:
import tkinter as tk
from tkinter import filedialog
import qrcode
from PIL import ImageTk
class QRGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("QR Code Generator")
self.root.geometry("500x550")
self.root.resizable(False, False)
self.qr_image = None
# Input section
input_frame = tk.Frame(root, pady=10)
input_frame.pack(fill="x", padx=20)
tk.Label(input_frame, text="Enter text or URL:").pack(anchor="w")
self.entry = tk.Entry(input_frame, width=50)
self.entry.pack(fill="x", pady=5)
What does this code do?
The first four lines import the libraries you need. tkinter provides the GUI framework, filedialog handles file save dialogs, qrcode generates QR codes, and ImageTk converts images for Tkinter display.
The QRGeneratorApp class wraps the entire application. Inside __init__, you configure the window title, set a fixed size of 500x550 pixels, and disable resizing so the layout stays consistent.
The input section creates a Frame container with padding, adds a text label, and places an Entry widget where users will type their text or URL.
- Save qr_generator.py.
Add the Generate button and image display area
Your window needs interactive controls. You'll add a Generate button to trigger QR code creation, a label area to display the result, and a Save button for exporting the image.
- In qr_generator.py, find the line that says self.entry.pack(fill="x", pady=5), then paste the following code below it:
# Generate button
self.generate_btn = tk.Button(
root, text="Generate QR Code"
)
self.generate_btn.pack(pady=10)
# QR code display area
self.qr_label = tk.Label(root, text="Your QR code will appear here", pady=20)
self.qr_label.pack()
# Save button
self.save_btn = tk.Button(
root, text="Save QR Code", state="disabled"
)
self.save_btn.pack(pady=10)
What does this code do?
self.generate_btn creates a button labeled "Generate QR Code" that the user clicks to create a QR code. You'll wire it to the generation function in the next step.
self.qr_label is a Label widget that starts with placeholder text. Once a QR code is generated, this label will display the image instead.
self.save_btn starts in a disabled state so users can't click it until a QR code exists to save.
- Save qr_generator.py.
Seeing a red underline or indent error?
Make sure the new code is indented inside the __init__ method (two levels of indentation, or 8 spaces). Every line should align with the self.entry.pack(fill="x", pady=5) line above it.
help me fix indentation errors in my Tkinter application
Run the application
The application needs an entry point that creates the window and starts the event loop. The mainloop() call keeps the window open and listening for user interactions.
- At the very bottom of qr_generator.py (outside the class, with no indentation), paste the following code:
if __name__ == "__main__":
root = tk.Tk()
app = QRGeneratorApp(root)
root.mainloop()
What does this code do?
if __name__ == "__main__" ensures this block only runs when you execute the file directly (not when importing it as a module).
root = tk.Tk() creates the main Tkinter window. QRGeneratorApp(root) builds your application inside it. root.mainloop() starts the event loop that keeps the window open and responsive to clicks and typing.
- Save qr_generator.py.
- Switch back to your terminal and navigate to your Desktop by running this command:
cd ~/Desktop
- Run your application by running this command:
python3 qr_generator.py
A window titled "QR Code Generator" should appear on your screen with a text input field, a Generate QR Code button, placeholder text where the QR code will appear, and a grayed-out Save QR Code button.
- Close the window by clicking the red close button (macOS) or the X button (Windows) to stop the application.
Window not appearing?
Make sure you saved the file before running the command. Check your terminal for error messages.
If you see IndentationError, verify that the if __name__ block has zero indentation (it sits outside the class).
If you see ModuleNotFoundError: No module named 'qrcode', re-run pip install "qrcode[pil]" from your terminal.
help me troubleshoot why my Tkinter window isn't appearing
✔️ Awesome, I've got everything!
Great. Double check you've saved your file and closed the application window before moving on.
ⓧ I'd like to double check the full code
Here is the full qr_generator.py file at this point. The button command parameters shown below will be wired to their functions in the next step.
import tkinter as tk
from tkinter import filedialog
import qrcode
from PIL import ImageTk
class QRGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("QR Code Generator")
self.root.geometry("500x550")
self.root.resizable(False, False)
self.qr_image = None
# Input section
input_frame = tk.Frame(root, pady=10)
input_frame.pack(fill="x", padx=20)
tk.Label(input_frame, text="Enter text or URL:").pack(anchor="w")
self.entry = tk.Entry(input_frame, width=50)
self.entry.pack(fill="x", pady=5)
# Generate button
self.generate_btn = tk.Button(
root, text="Generate QR Code", command=self.generate_qr
)
self.generate_btn.pack(pady=10)
# QR code display area
self.qr_label = tk.Label(root, text="Your QR code will appear here", pady=20)
self.qr_label.pack()
# Save button
self.save_btn = tk.Button(
root, text="Save QR Code", command=self.save_qr, state="disabled"
)
self.save_btn.pack(pady=10)
if __name__ == "__main__":
root = tk.Tk()
app = QRGeneratorApp(root)
root.mainloop()
Your application window is alive. Next up, you'll write the function that actually generates a QR code from the text input and displays it inside the window.
Generate and Display the QR Code
Your window is set up with an input field, a Generate button, and a placeholder label. Now it's time to make the button actually do something.
When the user clicks Generate, your app needs to read the text from the input field, encode it into a QR code matrix, and display the result as an image inside the window. This is the core logic of the entire application.
In this step, get ready to:
- Write the QR generation function that encodes user input into a QR code image.
- Display the generated QR code inside the application window.
- Test the full generation flow with a real URL.
Write the QR generation function
The qrcode library handles the heavy lifting of encoding text into a QR code matrix. Your function reads whatever the user typed, passes it through the encoder, and produces a Pillow image object.
- In qr_generator.py, find the closing line of the __init__ method (the last self.save_btn.pack(pady=10) line).
- Add the generate_qr method below it by copying the following code:
def generate_qr(self):
data = self.entry.get()
if not data:
return
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(data)
qr.make(fit=True)
self.qr_image = qr.make_image(fill_color="black", back_color="white")
What does this code do?
- self.entry.get() reads whatever text the user typed into the input field.
- The if not data: return guard prevents generating a blank QR code if the field is empty.
- qrcode.QRCode() creates a QR code encoder. Setting version=None with fit=True lets the library automatically pick the smallest QR size that fits your data.
- qr.make_image() renders the QR matrix into a Pillow image with black squares on a white background.
Display the QR code in the window
Generating the image is only half the job. Tkinter cannot display Pillow images directly. You need to convert the image into a format Tkinter understands, then attach it to the Label widget.
- Still inside qr_generator.py, add the following code directly below the self.qr_image = qr.make_image(...) line you just added (still inside the generate_qr method):
# Resize for display
display_image = self.qr_image.resize((300, 300))
self.tk_image = ImageTk.PhotoImage(display_image)
self.qr_label.config(image=self.tk_image, text="")
self.qr_label.image = self.tk_image
self.save_btn.config(state="normal")
What does this code do?
- .resize((300, 300)) scales the QR code to fit nicely in the window. The original is kept at full resolution for saving later.
- ImageTk.PhotoImage() converts the Pillow image into a Tkinter-compatible format that Labels can display.
- self.qr_label.config(image=self.tk_image, text="") swaps the placeholder text for the QR code image.
- self.qr_label.image = self.tk_image keeps a reference to the image so Python's garbage collector doesn't delete it. Without this line, Tkinter would show an empty box.
- self.save_btn.config(state="normal") enables the Save button now that there's something to save.
Why keep a reference to the image?
Tkinter does not keep its own Python reference to image objects. When the last Python reference to a PhotoImage is deleted, the image data is deleted too, and Tkinter displays an empty box where the image was.
By assigning self.qr_label.image = self.tk_image, you create a persistent reference that lives as long as the label does. This prevents the garbage collector from clearing your QR code.
- Save qr_generator.py.
- The Generate button was already wired to self.generate_qr in the previous step via the command parameter. Now that the method exists, the button is fully functional.
Seeing an error when you save?
- Make sure the generate_qr method is indented at the same level as __init__ (one level inside the class).
- Check that you have a blank line between the end of __init__ and the def generate_qr(self): line.
- help me fix an indentation error in my QR generator class
Test the generation
- Run the app by executing this command in your terminal:
python3 qr_generator.py
- Type https://nextwork.org into the text field.
- Click the Generate QR Code button.
You should see a black-and-white QR code appear in the window where the placeholder text used to be. The Save QR Code button should no longer be grayed out.
QR code not appearing?
- If the window opens but nothing happens when you click Generate, make sure the input field is not empty. The function silently returns if there is no text.
- If you see an error about generate_qr not being defined, check that the method name matches exactly (including the underscore).
- If the label shows an empty area instead of the QR code, confirm that self.qr_label.image = self.tk_image is present. This reference prevents Tkinter from garbage-collecting the image.
- help me debug why my QR code is not displaying in the Tkinter window
✔️ Awesome, I've got everything!
Great. Make sure you've saved qr_generator.py before moving on.
ⓧ I'd like to double check the full code
Here is the complete qr_generator.py file at this point:
import tkinter as tk
from tkinter import filedialog
import qrcode
from PIL import ImageTk
class QRGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("QR Code Generator")
self.root.geometry("500x550")
self.root.resizable(False, False)
self.qr_image = None
# Input section
input_frame = tk.Frame(root, pady=10)
input_frame.pack(fill="x", padx=20)
tk.Label(input_frame, text="Enter text or URL:").pack(anchor="w")
self.entry = tk.Entry(input_frame, width=50)
self.entry.pack(fill="x", pady=5)
# Generate button
self.generate_btn = tk.Button(
root, text="Generate QR Code", command=self.generate_qr
)
self.generate_btn.pack(pady=10)
# QR code display area
self.qr_label = tk.Label(root, text="Your QR code will appear here", pady=20)
self.qr_label.pack()
# Save button
self.save_btn = tk.Button(
root, text="Save QR Code", command=self.save_qr, state="disabled"
)
self.save_btn.pack(pady=10)
def generate_qr(self):
data = self.entry.get()
if not data:
return
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(data)
qr.make(fit=True)
self.qr_image = qr.make_image(fill_color="black", back_color="white")
# Resize for display
display_image = self.qr_image.resize((300, 300))
self.tk_image = ImageTk.PhotoImage(display_image)
self.qr_label.config(image=self.tk_image, text="")
self.qr_label.image = self.tk_image
self.save_btn.config(state="normal")
if __name__ == "__main__":
root = tk.Tk()
app = QRGeneratorApp(root)
root.mainloop()
Your QR code generator is already producing scannable images from any text you type. Next up, you'll add the ability to save those QR codes as PNG files anywhere on your computer.
Add Save Functionality
Your app can generate QR codes and display them in the window. The missing piece is getting that QR code out of the application and into a file you can actually share or print.
In this step, you'll write a save function that opens your operating system's native file picker. This lets the user choose exactly where to export their QR code as a PNG file.
In this step, get ready to:
- Confirm the Save button is wired up and ready.
- Write the save function to export QR codes as PNG files.
- Test the complete generate-and-save workflow.
Locate the Save button in your code
When you built the application window in an earlier step, you already placed a Save button in the layout. Take a look at this section inside your __init__ method:
# Save button
self.save_btn = tk.Button(
root, text="Save QR Code", command=self.save_qr, state="disabled"
)
self.save_btn.pack(pady=10)
Why is the button disabled?
The state="disabled" parameter grays out the button when the app first opens. There's no QR code to save yet, so disabling it prevents errors.
Your generate_qr method already enables this button with self.save_btn.config(state="normal") after a QR code is created. Now you need to write the save_qr method that the button calls.
Write the save function
The filedialog module from Tkinter provides native file picker dialogs that look and feel like your operating system's built-in save windows.
- In qr_generator.py, find the end of the generate_qr method (after the line self.save_btn.config(state="normal")).
- Add the following save_qr method below it:
def save_qr(self):
if self.qr_image is None:
return
file_path = filedialog.asksaveasfilename(
defaultextension=".png",
filetypes=[("PNG files", "*.png"), ("All files", "*.*")],
)
if file_path:
self.qr_image.save(file_path)
What does this code do?
The if self.qr_image is None: return guard prevents the function from running if no QR code has been generated yet. This is a safety check in case the button state gets out of sync.
The filedialog.asksaveasfilename call opens a native Save As dialog. The defaultextension=".png" parameter automatically appends .png if the user doesn't type a file extension.
The filetypes parameter controls the file type filter dropdown in the dialog. If the user cancels the dialog, file_path will be an empty string, so if file_path: ensures we only save when a valid path is selected.
- Save qr_generator.py.
Seeing a NameError for save_qr?
Make sure the save_qr method is indented at the same level as generate_qr inside the QRGeneratorApp class. Python is sensitive to indentation levels.
Also confirm the method is placed after the generate_qr method but before the if __name__ == "__main__": block at the bottom of the file.
Help me debug my save_qr method placement
Test the full workflow
Time to run through the entire generate-and-save flow to make sure everything works end to end.
- Run the application by executing this command in your terminal:
python3 qr_generator.py
- Type a URL into the text field (for example, https://nextwork.org).
- Click Generate QR Code.
- Confirm the QR code image appears in the window and the Save QR Code button is no longer grayed out.
- Click Save QR Code.
- In the file picker dialog that appears, choose a location (like your Desktop) and give the file a name.
- Click Save.
- Navigate to the location you chose and confirm the PNG file exists.
- Open your phone's camera app and scan the QR code image to verify it encodes the URL you typed.
What should I see?
The file picker dialog should look like your operating system's standard Save As window. After saving, you should find a PNG image file at your chosen location. Scanning it with your phone should open the URL you entered.
Save dialog not appearing?
Make sure you generated a QR code first. The Save button stays disabled until a QR code exists in the window.
If the dialog appears but the file is not created, check that you have write permissions to the folder you selected. Try saving to your Desktop instead.
Help me troubleshoot my QR code save functionality
✔️ Awesome, I've got everything!
Great. Double check you've saved your file and your QR code PNG exported successfully.
ⓧ I'd like to double check the full code
Here is the complete qr_generator.py file at this point:
import tkinter as tk
from tkinter import filedialog
import qrcode
from PIL import ImageTk
class QRGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("QR Code Generator")
self.root.geometry("500x550")
self.root.resizable(False, False)
self.qr_image = None
# Input section
input_frame = tk.Frame(root, pady=10)
input_frame.pack(fill="x", padx=20)
tk.Label(input_frame, text="Enter text or URL:").pack(anchor="w")
self.entry = tk.Entry(input_frame, width=50)
self.entry.pack(fill="x", pady=5)
# Generate button
self.generate_btn = tk.Button(
root, text="Generate QR Code", command=self.generate_qr
)
self.generate_btn.pack(pady=10)
# QR code display area
self.qr_label = tk.Label(root, text="Your QR code will appear here", pady=20)
self.qr_label.pack()
# Save button
self.save_btn = tk.Button(
root, text="Save QR Code", command=self.save_qr, state="disabled"
)
self.save_btn.pack(pady=10)
def generate_qr(self):
data = self.entry.get()
if not data:
return
qr = qrcode.QRCode(
version=None,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(data)
qr.make(fit=True)
self.qr_image = qr.make_image(fill_color="black", back_color="white")
# Resize for display
display_image = self.qr_image.resize((300, 300))
self.tk_image = ImageTk.PhotoImage(display_image)
self.qr_label.config(image=self.tk_image, text="")
self.qr_label.image = self.tk_image
self.save_btn.config(state="normal")
def save_qr(self):
if self.qr_image is None:
return
file_path = filedialog.asksaveasfilename(
defaultextension=".png",
filetypes=[("PNG files", "*.png"), ("All files", "*.*")],
)
if file_path:
self.qr_image.save(file_path)
if __name__ == "__main__":
root = tk.Tk()
app = QRGeneratorApp(root)
root.mainloop()
Secret mission
Custom Color QR Codes
Your QR codes work, but they all look the same. What if you could generate QR codes in any color combination you want? Take your generator to the next level by adding foreground and background color inputs with built-in error handling.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- The qr_generator.py file on your Desktop.
- Any saved QR code PNG files.
- Pip packages: qrcode and Pillow.
Keep everything running
No action needed. Choose this if you plan to keep experimenting with your QR code generator or want to extend it further.
- Your qr_generator.py file stays on your Desktop, ready to run anytime.
- The qrcode and Pillow packages remain installed and available for other Python projects.
Pause - I'll come back to this later
Close the application window if it is still running. Your files and packages stay in place for when you return.
- Close the QR Code Generator window.
- Your qr_generator.py file and any saved PNG files remain on disk.
- To resume later, open a terminal, navigate to your Desktop, and run python3 qr_generator.py.
Delete - I don't want to use this again
Remove all project files and uninstall the packages you installed during this project.
- Delete your project file by running this command (macOS/Linux):
cd ~/Desktop
rm qr_generator.py
On Windows, run this instead:
cd ~\Desktop
del qr_generator.py
- Delete any saved QR code PNG files from the locations where you saved them.
- Uninstall the pip packages by running:
pip uninstall qrcode pillow -y
- Confirm the packages are removed by running:
python3 -c "import qrcode"
You should see a ModuleNotFoundError, which confirms the package is gone.
Nice Work!
Nice Work!
You just built a fully functional desktop application from scratch using Python. Your QR code generator takes any text or URL and turns it into a scannable image, all through a graphical interface you created yourself.
You've learned how to:
- Built a complete Tkinter GUI application with input fields, buttons, and dynamic image display.
- Integrated the qrcode library to generate QR codes programmatically and used Pillow's ImageTk module to display them inside a Tkinter window.
- Implemented native file save dialogs with tkinter.filedialog to export QR codes as PNG files.
- Added custom color support with input validation and error handling for personalized QR codes.
Ready to quiz yourself?