Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
How to add PDF in Tkinter GUI Python?
This article will teach us how to display PDF files in the Tkinter GUI. We will be using the PyMuPDF library to read the PDF files and convert them into images which will then be displayed using Tkinter.
For our task, we will do the following steps ?
Read the PDF file
Define a transformation matrix to apply on the pages of PDF to get their images
Count the total number of pages for error checking
Define the screen (the canvas) for our GUI
Define a helper function for converting a PDF page to a PIL image
Define a function to show the image of a page in our GUI
Add buttons, labels, scrollbars etc and configure them
Installing Required Libraries
To get started, let's first install the PyMuPDF package by running the following command in our terminal ?
python -m pip install --upgrade pip python -m pip install --upgrade pymupdf
Importing Libraries
Now we need to import the libraries we will be working with ?
import fitz from tkinter import * from PIL import Image, ImageTk
Here fitz is a utility library that comes along with the PyMuPDF library and is used to get PDF pages as images.
Opening the PDF File
We first open the PDF file we want to display in our GUI by using the fitz.open() function. This returns a document object which can be used to access pages ?
# open pdf file file_name = "sample.pdf" doc = fitz.open(file_name)
Setting Up Transformation Matrix
Now we need to specify how we would like to view the pages. By defining the below matrix function we tell fitz to keep a 1x zoom ?
# transformation matrix we can apply on pages zoom = 1 mat = fitz.Matrix(zoom, zoom)
Counting Pages
Let us also count the number of pages ?
# count number of pages
num_pages = 0
for p in doc:
num_pages += 1
Creating the GUI Components
Now we will define a screen, add a scroll bar and a canvas to our code ?
# initialize and set screen size
root = Tk()
root.geometry('750x700')
# add scroll bar
scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
# add canvas
canvas = Canvas(root, yscrollcommand=scrollbar.set)
canvas.pack(side=LEFT, fill=BOTH, expand=1)
Here our screen is represented by the name "root" and is of dimensions 750x700. We have also added a scroll bar and specified it to be on the right side and fill the entire height. Similarly, we have added the canvas to the left side and fill the entire screen on both sides.
Adding Input Fields
In order to receive the page number the user wants to read, we need to take the page number as an input. We can do it as follows ?
# define entry point (field for taking inputs) entry = Entry(root) # add a label for the entry point label = Label(root, text="Enter page number to display:")
The arguments 'root' tell us that the objects will be associated with the screen "root".
Helper Function for PDF to Image Conversion
Now we will define a helper function to get the image of the PDF file from a page number ?
def pdf_to_img(page_num):
page = doc.load_page(page_num)
pix = page.get_pixmap(matrix=mat)
return Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
Here we first load the page using doc.load_page and passing the page number as an argument. Then we convert the PDF page to get pixel representation of that page in the second line. Finally, we convert the pixel representation into the PIL Image format.
Function to Display Images
Now we define a function show_image to display the image in our Tkinter GUI ?
def show_image():
try:
page_num = int(entry.get()) - 1
assert page_num >= 0 and page_num < num_pages
im = pdf_to_img(page_num)
img_tk = ImageTk.PhotoImage(im)
frame = Frame(canvas)
panel = Label(frame, image=img_tk)
panel.pack(side="bottom", fill="both", expand="yes")
frame.image = img_tk
canvas.create_window(0, 0, anchor='nw', window=frame)
frame.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all"))
except:
pass
Here first we read the page number from the entry point we defined earlier and convert it to an integer. If it's not a valid integer, an exception occurs and the exception block handles it. We then check if the page number is between 0 or the number of pages since that is the only valid range of pages we can display. Then using our previously defined helper function, we get a PIL Image of the user specified page. We then set the frame, panel and the canvas to appropriately display this image.
Adding Button and Configuring Layout
Next we add a button to display the page. We pass the function show_image as a command. Hence whenever the button is pressed the show_image function will be called ?
# add button to display pages button = Button(root, text="Show Page", command=show_image)
Now we set the visual locations of the various components we defined previously ?
# set visual locations label.pack(side=TOP, fill=None) entry.pack(side=TOP, fill=BOTH) button.pack(side=TOP, fill=None)
Final Configuration
We also set the initial page as the first page of the PDF as follows ?
entry.insert(0, '1') show_image()
We configure the scroll bar and start the main loop ?
scrollbar.config(command=canvas.yview) root.mainloop()
Finally we close the PDF so it doesn't get corrupted ?
doc.close()
Complete Example
Here's the complete working code ?
import fitz
from tkinter import *
from PIL import Image, ImageTk
# open pdf file
file_name = "sample.pdf"
doc = fitz.open(file_name)
# transformation matrix
zoom = 1
mat = fitz.Matrix(zoom, zoom)
# count number of pages
num_pages = len(doc)
# initialize GUI
root = Tk()
root.geometry('750x700')
root.title('PDF Viewer')
# add scroll bar
scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
# add canvas
canvas = Canvas(root, yscrollcommand=scrollbar.set)
canvas.pack(side=LEFT, fill=BOTH, expand=1)
# input components
label = Label(root, text="Enter page number to display:")
entry = Entry(root)
def pdf_to_img(page_num):
page = doc.load_page(page_num)
pix = page.get_pixmap(matrix=mat)
return Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
def show_image():
try:
page_num = int(entry.get()) - 1
assert 0 <= page_num < num_pages
im = pdf_to_img(page_num)
img_tk = ImageTk.PhotoImage(im)
frame = Frame(canvas)
panel = Label(frame, image=img_tk)
panel.pack(side="bottom", fill="both", expand="yes")
frame.image = img_tk
canvas.create_window(0, 0, anchor='nw', window=frame)
frame.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all"))
except:
pass
# add button
button = Button(root, text="Show Page", command=show_image)
# layout configuration
label.pack(side=TOP, fill=None)
entry.pack(side=TOP, fill=BOTH)
button.pack(side=TOP, fill=None)
# initialize with first page
entry.insert(0, '1')
show_image()
# configure scrollbar and start
scrollbar.config(command=canvas.yview)
root.mainloop()
# cleanup
doc.close()
Output
After running the program we see the following output ?
Conclusion
This article taught us how to use the PyMuPDF library along with Pillow and Tkinter to display PDF files in a GUI. We learned how to convert PDF pages to images, create interactive navigation, and handle user input for page selection.
