0

In my program, I am trying to have the GUI display the name of the PDF that I select BEFORE I have the program actually executing what it is supposed to do with that PDF. As of right now, an individual can open a file directory, select a file, and then press the run button in the GUI to have the program execute, however the user cannot see the name of the file that they selected.

I have tried placing a simple "print" function, but that hasn't seemed to work, as well as adding "selector.filename" ato lbl1, as well as making it its own label and placed it in different areas, including almost at the end of all the code, however that hasn't seemed to have worked.

import os
import PyPDF2
import pandas
import webbrowser
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from nltk.stem.wordnet import WordNetLemmatizer
from nltk.tokenize import word_tokenize

#----Functions----#

#Method that a PDF that is read into the program goes through to eliminate any unwanted words or symbols#
def preprocess(text):
    #Filters out punctuation from paragraph witch becomes tokenized to words and punctuation#
    tokenizer = RegexpTokenizer(r'\w+')
    result = tokenizer.tokenize(text)

    #Makes all words lowercase#
    words = [item.lower() for item in result]

    #Removes all remaining tokens that are not alphabetic#
    result = [word for word in words if word.isalpha()]

    #Imports stopwords to be removed from paragraph#
    stop_words = set(stopwords.words("english"))

    #Removes the stop words from the paragraph#
    filtered_sent = []
    for w in result:
        if w not in stop_words:
            filtered_sent.append(w)

    #Return word to root word/chop-off derivational affixes#
    ps = PorterStemmer()
    stemmed_words = []
    for w in filtered_sent:
        stemmed_words.append(ps.stem(w))

    #Lemmatization, which reduces word to their base word, which is linguistically correct lemmas#
    lem = WordNetLemmatizer()
    lemmatized_words = ' '.join([lem.lemmatize(w,'n') and lem.lemmatize(w,'v') for w in filtered_sent])

    #Re-tokenize lemmatized words string#
    tokenized_word = word_tokenize(lemmatized_words)
    return tokenized_word

#Wraps two functions inside an object which allows both functions to use filename#
class PDFSelector:
    #Creates global variable 'filename'#
    def __init(self):
        self.filename = ""

    #Allows user to select PDF to use in program#
    def select_PDF(self):
        #Opens file directory to select a file, and shows both folders and PDF files only#
        self.filename = filedialog.askopenfilename(initialdir = "/", title = "Select file", filetypes = (("pdf files", "*.pdf"), ("all files", "*.*")))
        print(self.filename)

    #Method for PDF to run through to convert it into text, then print it out in a browser#
    def run_program(self):    
        #Loads in PDF into program#
        PDF_file = open(self.filename, 'rb')
        read_pdf = PyPDF2.PdfFileReader(PDF_file)

        #Determines number of pages in PDF file and sets the document content to 'null'#
        number_of_pages = read_pdf.getNumPages()
        doc_content = ""

        #Extract text from the PDF file#
        for i in range(number_of_pages):
            page = read_pdf.getPage(0)
            page_content = page.extractText()
            doc_content += page_content

        #Turns the text drawn from the PDF file into data the remaining code can understand#
        tokenized_words = preprocess(doc_content)

        #Determine frequency of words tokenized + lemmatized text#
        from nltk.probability import FreqDist
        fdist = FreqDist(tokenized_words)
        final_list = fdist.most_common(len(fdist))

        #Organize data into two columns and export the data to an html that automatically opens#
        df = pandas.DataFrame(final_list, columns = ["Word", "Frequency"])
        df.to_html('word_frequency.html')
        webbrowser.open('file://' + os.path.realpath('word_frequency.html'))      

#----Main----#

#Creates an instance of the wrapped functions to use the GUI#        
selector = PDFSelector()

#Creats the GUI that will be used to select inputs#
window = tk.Tk()
window.geometry("385x130")
window.resizable(0, 0)
window.title("Word Frequency Program")

#Code literally just to make the GUI look better#
lblfilla = tk.Label(window, text = "   ").grid(row = 0, column = 0)
lblfillb = tk.Label(window, text = "   ").grid(row = 0, column = 1)
lblfillc = tk.Label(window, text = "   ").grid(row = 0, column = 2)
lblfilld = tk.Label(window, text = "   ").grid(row = 0, column = 3)
lblfille = tk.Label(window, text = "   ").grid(row = 0, column = 4)
lblfillf = tk.Label(window, text = "   ").grid(row = 1, column = 0)
lblfillg = tk.Label(window, text = "   ").grid(row = 2, column = 0)
lblfillh = tk.Label(window, text = "   ").grid(row = 3, column = 0)
lblfilli = tk.Label(window, text = "   ").grid(row = 4, column = 0)

#Just a simple label on the GUI#
lbl1 = tk.Label(window, text = "File Selected: ").grid(row = 1, column = 1)

#Label asking for input to determine number of words to be displayed in the data table# (NOT IMPLEMENTED YET)
lbl2 = tk.Label(window, text = "Number of Words: ").grid(row = 2, column = 1)
lbl2a = tk.Entry(window).grid(row = 2, column = 2, columnspan = 2)

#Calls the select_PDF method to choose a PDF for the program to read#
button1 = ttk.Button(window, text = "Select File", command = selector.select_PDF).grid(row = 1, column = 4)

#Quits out of the program when certain button clicked#
button2 = ttk.Button(window, text = "Quit", command = window.quit).grid(row = 3, column = 2)

#Button to make the program execute#
button3 = ttk.Button(window, text = "Run", command = selector.run_program).grid(row = 3, column = 3)

lbl4 = tk.Label(window, text = selector.filename).grid(row = 1, column = 2)


window.mainloop()
window.destroy()

As of right now, after a the PDF file is selected it should display next to "file Selected: " in the GUI

Lofton Gentry
  • 189
  • 1
  • 13

1 Answers1

0

I'd suggest setting the textvariable in your Label variable, lbl1, to some StringVar. Then you can set the variable in select_PDF() and let tk handle updating the GUI for you.

See this answer.

Curtis2point0
  • 30
  • 1
  • 6
  • so I changed some of the code in the main section to `file_name = StringVar(), lbl1 = tk.Label(window, text = "File Selected: ").grid(row = 1, column = 1), lbl1a = tk.Label(window, text = file_name).grid(row = 1, column = 2)` and in select_PDF, I had `file_name.set(self.filename)`, but my code keeps displaying the same name, however something is appearing now, I'm just not sure how to have it change now – Lofton Gentry Jul 29 '19 at 19:43
  • Be sure you are setting `textvariable` of Label. So for your second Label set it like `lbl1a = tk.Label(window, textvariable = file_name)`, then when you set it tk will handle the update. – Curtis2point0 Jul 29 '19 at 19:53
  • Nothing appears still, is it because there is something blocking it, or the color of the text and background are the same? – Lofton Gentry Jul 29 '19 at 20:05
  • I doubt it's font or anything unless you changed the defaults. Check the scope of your StringVar in relation to your PDFSelector class. Make sure your StringVar is outside the class scope so your main section can access it also. Try changing your StringVar outside the class and make sure that works too. – Curtis2point0 Jul 29 '19 at 20:32