Today, we’re diving into a cool project where we’ll build our own PDF viewer using Python. Imagine having a little app on your computer that lets you open and read PDF documents, just like Adobe Reader, but you made it yourself!
In today’s article, we are going to create a PDF viewer in Python using the tkinter
and PyMuPDF
libraries, that will allow us to open a PDF file, display its content, and scroll through it using a scrollbar.
Learn also: How to Extract Tables from PDF in Python
Let’s get started!
Table of Contents
- Necessary Libraries
- Imports
- PDF File Viewer Functions
- Loading and Displaying the PDF
- Creating a Label For Displaying a PDF
- Handling Closing the Application
- Creating a Canvas and Scrollbar and Configuring the Scrollbars
- Create the Main Window
- Create the Open PDF Button
- Create a Canvas and Scrollbar For Scrolling
- Starting the tkinter Main Loop
- Example
- Full Code
Necessary Libraries
For the code to function properly, make sure to install these libraries via your terminal or command prompt:
$ pip install PyMuPDF
The PyMuPDF library allows us to work with PDF files in our Python program.
$ pip install tk
The tkinter library allows the creation of a graphical user interface (GUI).
Imports
import fitz # PyMuPDF
from tkinter import *
from tkinter import filedialog
We start by importing the PyMuPDF
library, a Python module for working with PDF files. Additionally, we import all classes and functions from the tkinter
library, along with the filedialog
module from tkinter
, which is used for opening and saving files via a file dialog.
PDF File Viewer Functions
def open_pdf():
file_path = filedialog.askopenfilename(initialdir="/", title="Select a PDF file",
filetypes=(("PDF Files", "*.pdf"), ("All Files", "*.*")))
Next, we create a function designed to handle the opening and selection of a PDF file by launching a file dialog. This dialog allows the user to select a file to open, with the initial directory set to the root directory (‘/’).
The file dialog is named and presented to the user with a prompt, specifying the file types that can be selected. In this case, it permits the selection of PDF files with the extension ‘.pdf’ and files of any type with ‘.’. Essentially, this function enables the choice of any file from the directory.
Loading and Displaying the PDF
if file_path:
pdf_viewer = fitz.open(file_path)
page = pdf_viewer.load_page(0) # Load the first page
img = page.get_pixmap()
img.save("temp.png") # Convert the page to a temporary image file
This part of the code checks if the file_path
variable, obtained from filedialog
in the previous part of the code, contains a valid file path. If a file is selected (in other words, file_path
is not an empty string), the code proceeds with further processing. It then opens the PDF file specified by file_path
using the PyMuPDF (fitz) library, creating a pdf_viewer
object. This object allows interaction with the contents of the PDF file. Subsequently, it loads the first page of the PDF document, obtaining a reference to the first page and storing it in the page
variable.
The parameter 0
represents the page number (PDF pages are zero-indexed, so 0
refers to the first page) after that, it extracts the content of the loaded page as an image (pixmap
). The content of the page is essentially converted into an image, which you can further manipulate or save.
Lastly, the last line of the code saves the extracted page as a temporary image file named temp.png
. It effectively converts the first page of the PDF into a PNG image file. You can specify a different filename or format if needed. In simple terms, this function takes the first page of the PDF and saves it as a picture that you can view or use later after checking if you have selected a PDF file using filedialog
.
Creating a Label For Displaying a PDF
img_data = PhotoImage(file="temp.png")
img_label = Label(canvas, image=img_data)
img_label.image = img_data # Keep a reference
Now we create this code that displays the image “temp.png
” within the specified canvas in your GUI. This is a common way to display images in tkinter-based applications. You can further position and customize the Label and canvas as needed within your GUI layout.
Handling Closing the Application
# Delete the temporary image file when a new PDF is opened
root.protocol("WM_DELETE_WINDOW",
lambda: [img_data.blank(), img_data, img_label, pdf_viewer.close(), root.destroy()])
Then, we set up a protocol for the application’s main window. This protocol specifies what should happen when the user tries to close the window. It’s configured to :
- Clear image data.
- Close the PDF viewer.
- Destroy (close) the main application window.
Creating a Canvas and Scrollbar and Configuring the Scrollbars
# Add a canvas for scrolling and center it
canvas.create_window((0, 0), window=img_label, anchor="center")
canvas.config(scrollregion=canvas.bbox("all"))
Here we created a canvas, which is a scrollable area, within the main window. This canvas is used to display the PDF page then we also create a scrollbar for the canvas to allow scrolling.
Create the Main Window
# Create the main tkinter window
root = Tk()
root.title("Simple PDF Viewer - The Pycodes")
root.geometry("620x600")
After that, we create the main application window using tkinter
and set its title and size.
Create the Open PDF Button
# Create an "Open PDF" button
open_button = Button(root, text="Open PDF", command=open_pdf, width=20, font="Arial 16", bd=4, relief=RAISED)
open_button.pack(pady=10)
Following that, we create a button labeled “Open PDF” that, when clicked, will execute the open_pdf()
function. We set some properties for the button, like its size, font, and appearance.
Create a Canvas and Scrollbar For Scrolling
canvas = Canvas(root)
canvas.pack(fill=BOTH, expand=True)
scrollbar = Scrollbar(canvas, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.config(yscrollcommand=scrollbar.set)
Here, we configured the canvas to work with the scrollbar for vertical scrolling.
Starting the tkinter Main Loop
# Start the tkinter main loop
root.mainloop()
Finally, we start the main loop of the GUI application by calling root.mainloop()
. This loop keeps the program running and responsive to user interactions.
Example
Full Code
import fitz # PyMuPDF
from tkinter import *
from tkinter import filedialog
def open_pdf():
file_path = filedialog.askopenfilename(initialdir="/", title="Select a PDF file",
filetypes=(("PDF Files", "*.pdf"), ("All Files", "*.*")))
if file_path:
pdf_viewer = fitz.open(file_path)
page = pdf_viewer.load_page(0) # Load the first page
img = page.get_pixmap()
img.save("temp.png") # Convert the page to a temporary image file
img_data = PhotoImage(file="temp.png")
img_label = Label(canvas, image=img_data)
img_label.image = img_data # Keep a reference
# Delete the temporary image file when a new PDF is opened
root.protocol("WM_DELETE_WINDOW",
lambda: [img_data.blank(), img_data, img_label, pdf_viewer.close(), root.destroy()])
# Add a canvas for scrolling and center it
canvas.create_window((0, 0), window=img_label, anchor="center")
canvas.config(scrollregion=canvas.bbox("all"))
# Create the main tkinter window
root = Tk()
root.title("Simple PDF Viewer - The Pycodes")
root.geometry("620x600")
# Create an "Open PDF" button
open_button = Button(root, text="Open PDF", command=open_pdf, width=20, font="Arial 16", bd=4, relief=RAISED)
open_button.pack(pady=10)
# Create a canvas and scrollbar for scrolling
canvas = Canvas(root)
canvas.pack(fill=BOTH, expand=True)
scrollbar = Scrollbar(canvas, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.config(yscrollcommand=scrollbar.set)
# Start the tkinter main loop
root.mainloop()
Happy Coding!