1
+ # importing everything from tkinter
2
+ from tkinter import *
3
+ # importing ttk for styling widgets from tkinter
4
+ from tkinter import ttk
5
+ # importing filedialog from tkinter
6
+ from tkinter import filedialog as fd
7
+ # importing os module
8
+ import os
9
+ # importing the PDFMiner class from the miner file
10
+ from miner import PDFMiner
11
+
12
+
13
+
14
+ # creating a class called PDFViewer
15
+ class PDFViewer :
16
+ # initializing the __init__ / special method
17
+ def __init__ (self , master ):
18
+ # path for the pdf doc
19
+ self .path = None
20
+ # state of the pdf doc, open or closed
21
+ self .fileisopen = None
22
+ # author of the pdf doc
23
+ self .author = None
24
+ # name for the pdf doc
25
+ self .name = None
26
+ # the current page for the pdf
27
+ self .current_page = 0
28
+ # total number of pages for the pdf doc
29
+ self .numPages = None
30
+ # creating the window
31
+ self .master = master
32
+ # gives title to the main window
33
+ self .master .title ('PDF Viewer' )
34
+ # gives dimensions to main window
35
+ self .master .geometry ('580x520+440+180' )
36
+ # this disables the minimize/maximize button on the main window
37
+ self .master .resizable (width = 0 , height = 0 )
38
+ # loads the icon and adds it to the main window
39
+ self .master .iconbitmap (self .master , 'pdf_file_icon.ico' )
40
+ # creating the menu
41
+ self .menu = Menu (self .master )
42
+ # adding it to the main window
43
+ self .master .config (menu = self .menu )
44
+ # creating a sub menu
45
+ self .filemenu = Menu (self .menu )
46
+ # giving the sub menu a label
47
+ self .menu .add_cascade (label = "File" , menu = self .filemenu )
48
+ # adding a two buttons to the sub menus
49
+ self .filemenu .add_command (label = "Open File" , command = self .open_file )
50
+ self .filemenu .add_command (label = "Exit" , command = self .master .destroy )
51
+ # creating the top frame
52
+ self .top_frame = ttk .Frame (self .master , width = 580 , height = 460 )
53
+ # placing the frame using inside main window using grid()
54
+ self .top_frame .grid (row = 0 , column = 0 )
55
+ # the frame will not propagate
56
+ self .top_frame .grid_propagate (False )
57
+ # creating the bottom frame
58
+ self .bottom_frame = ttk .Frame (self .master , width = 580 , height = 50 )
59
+ # placing the frame using inside main window using grid()
60
+ self .bottom_frame .grid (row = 1 , column = 0 )
61
+ # the frame will not propagate
62
+ self .bottom_frame .grid_propagate (False )
63
+ # creating a vertical scrollbar
64
+ self .scrolly = Scrollbar (self .top_frame , orient = VERTICAL )
65
+ # adding the scrollbar
66
+ self .scrolly .grid (row = 0 , column = 1 , sticky = (N ,S ))
67
+ # creating a horizontal scrollbar
68
+ self .scrollx = Scrollbar (self .top_frame , orient = HORIZONTAL )
69
+ # adding the scrollbar
70
+ self .scrollx .grid (row = 1 , column = 0 , sticky = (W , E ))
71
+ # creating the canvas for display the PDF pages
72
+ self .output = Canvas (self .top_frame , bg = '#ECE8F3' , width = 560 , height = 435 )
73
+ # inserting both vertical and horizontal scrollbars to the canvas
74
+ self .output .configure (yscrollcommand = self .scrolly .set , xscrollcommand = self .scrollx .set )
75
+ # adding the canvas
76
+ self .output .grid (row = 0 , column = 0 )
77
+ # configuring the horizontal scrollbar to the canvas
78
+ self .scrolly .configure (command = self .output .yview )
79
+ # configuring the vertical scrollbar to the canvas
80
+ self .scrollx .configure (command = self .output .xview )
81
+ # loading the button icons
82
+ self .uparrow_icon = PhotoImage (file = 'uparrow.png' )
83
+ self .downarrow_icon = PhotoImage (file = 'downarrow.png' )
84
+ # resizing the icons to fit on buttons
85
+ self .uparrow = self .uparrow_icon .subsample (3 , 3 )
86
+ self .downarrow = self .downarrow_icon .subsample (3 , 3 )
87
+ # creating an up button with an icon
88
+ self .upbutton = ttk .Button (self .bottom_frame , image = self .uparrow , command = self .previous_page )
89
+ # adding the button
90
+ self .upbutton .grid (row = 0 , column = 1 , padx = (270 , 5 ), pady = 8 )
91
+ # creating a down button with an icon
92
+ self .downbutton = ttk .Button (self .bottom_frame , image = self .downarrow , command = self .next_page )
93
+ # adding the button
94
+ self .downbutton .grid (row = 0 , column = 3 , pady = 8 )
95
+ # label for displaying page numbers
96
+ self .page_label = ttk .Label (self .bottom_frame , text = 'page' )
97
+ # adding the label
98
+ self .page_label .grid (row = 0 , column = 4 , padx = 5 )
99
+
100
+ # function for opening pdf files
101
+ def open_file (self ):
102
+ # open the file dialog
103
+ filepath = fd .askopenfilename (title = 'Select a PDF file' , initialdir = os .getcwd (), filetypes = (('PDF' , '*.pdf' ), ))
104
+ # checking if the file exists
105
+ if filepath :
106
+ # declaring the path
107
+ self .path = filepath
108
+ # extracting the pdf file from the path
109
+ filename = os .path .basename (self .path )
110
+ # passing the path to PDFMiner
111
+ self .miner = PDFMiner (self .path )
112
+ # getting data and numPages
113
+ data , numPages = self .miner .get_metadata ()
114
+ # setting the current page to 0
115
+ self .current_page = 0
116
+ # checking if numPages exists
117
+ if numPages :
118
+ # getting the title
119
+ self .name = data .get ('title' , filename [:- 4 ])
120
+ # getting the author
121
+ self .author = data .get ('author' , None )
122
+ self .numPages = numPages
123
+ # setting fileopen to True
124
+ self .fileisopen = True
125
+ # calling the display_page() function
126
+ self .display_page ()
127
+ # replacing the window title with the PDF document name
128
+ self .master .title (self .name )
129
+
130
+ # the function to display the page
131
+ def display_page (self ):
132
+ # checking if numPages is less than current_page and if current_page is less than
133
+ # or equal to 0
134
+ if 0 <= self .current_page < self .numPages :
135
+ # getting the page using get_page() function from miner
136
+ self .img_file = self .miner .get_page (self .current_page )
137
+ # inserting the page image inside the Canvas
138
+ self .output .create_image (0 , 0 , anchor = 'nw' , image = self .img_file )
139
+ # the variable to be stringified
140
+ self .stringified_current_page = self .current_page + 1
141
+ # updating the page label with number of pages
142
+ self .page_label ['text' ] = str (self .stringified_current_page ) + ' of ' + str (self .numPages )
143
+ # creating a region for inserting the page inside the Canvas
144
+ region = self .output .bbox (ALL )
145
+ # making the region to be scrollable
146
+ self .output .configure (scrollregion = region )
147
+
148
+ # function for displaying next page
149
+ def next_page (self ):
150
+ # checking if file is open
151
+ if self .fileisopen :
152
+ # checking if current_page is less than or equal to numPages-1
153
+ if self .current_page <= self .numPages - 1 :
154
+ # updating the page with value 1
155
+ self .current_page += 1
156
+ # displaying the new page
157
+ self .display_page ()
158
+
159
+ # function for displaying the previous page
160
+ def previous_page (self ):
161
+ # checking if fileisopen
162
+ if self .fileisopen :
163
+ # checking if current_page is greater than 0
164
+ if self .current_page > 0 :
165
+ # decrementing the current_page by 1
166
+ self .current_page -= 1
167
+ # displaying the previous page
168
+ self .display_page ()
169
+
170
+
171
+
172
+ # creating the root winding using Tk() class
173
+ root = Tk ()
174
+ # instantiating/creating object app for class PDFViewer
175
+ app = PDFViewer (root )
176
+ # calling the mainloop to run the app infinitely until user closes it
177
+ root .mainloop ()
0 commit comments