1

I am a newbie in python. I am trying to write a program to reference books, book chapters and journal articles in Harvard and APA style. I need to be able to print the entry from the user.

The code displays three windows. In the first, the user is asked to choose the referencing style (Harvard/APA) and when clicking the button it opens a second window which allows the user to choose the source (book/book chapter/journal). Then a third window opens which allows the user to input the information that is required (author/year/title and so on).

After this, the user must click another button done to see the full reference. To visualise the execution, select Harvard, then Book, as I have only written that part of the code.

from tkinter import *

def book_harvard():
    reference = author_entry.get()
    reference_1 = year_entry.get()
    reference_2 = title_entry.get()
    string_to_display = reference + reference_1 + reference_2
    print(string_to_display)


def TypeofTextHarvard():
    second = Toplevel(first)
    first.withdraw()
    second.title("Type of Source")
    Source = Label (second, text = "What type of source would you like to reference?").grid(column = 1, row = 0)
    Book = Button (second, text = "Book", command = Harvard).grid(column = 1, row = 1)
    Chapter = Button (second, text = "Book Chapter").grid (column = 1, row = 2)
    Journal = Button (second, text = "Journal Article").grid (column = 1, row = 3)

first = Tk()
first.title("Referencing Style")
Reference = Label (first, text = "Which referencing style would you like to use?").grid(column = 1, row = 0)
Harvard = Button (first, text = "Harvard Style", command = TypeofTextHarvard).grid (column = 1, row = 1)
APA = Button (first, text = "APA Style").grid (column = 1, row = 2)


def Harvard():
    third = Toplevel()
    third.title("book")
    author = StringVar()
    year = StringVar()
    title = StringVar()

    author_label = Label(third, text = "Author")
    author_entry = Entry(third)
    year_label = Label(third, text = "Year")
    year_entry = Entry(third)
    title_label = Label(third, text = "Title")
    title_entry = Entry(third)
    button_1 = Button(third, text = "Done", command = book_harvard)
    author_label_2 = Label(third, textvariable = author)
    year_label_2 = Label(third, textvariable = year)
    title_label_2 = Label(third, textvariable = title)

    author_label.grid (row = 0, column = 0)
    author_entry.grid (row = 0, column = 1)
    year_label.grid (row = 1, column = 0)
    year_entry.grid (row = 1, column = 1)
    title_label.grid (row = 2, column = 0)
    title_entry.grid (row = 2, column = 1)
    button_1.grid (row = 3, column = 0)
    author_label_2.grid (row = 4, column = 1)
    year_label_2.grid (row = 4, column = 2)
    title_label_2.grid (row = 4, column = 3)


first.mainloop()

However I get the following error:

reference = author_entry.get()
NameError: name 'author_entry' is not defined
martineau
  • 119,623
  • 25
  • 170
  • 301
Arlet
  • 75
  • 6
  • 1
    Names defined in a function do not exist after that function finishes executing and are not visible from outside of that function. A common way to hang on to names of things for longer is to make a class and assign to attributes of the instantiated class. (`self.author_entry = Entry(third)` and then in another method you can do `reference = self.author_entry.get()`) Another way is to have your functions return any relevant objects and assign those returned objects to names that you hang onto. Then pass those objects to other function. Yet another way is to use global variables. But don't. – Steven Rumbalski Apr 01 '19 at 16:07

1 Answers1

3

The cause of the NameError is because author_entry is a variable local to the Harvard() function, so can't be referenced outside of it, such as in the separate book_harvard() function. The simplest—although not the best—solution is to make it a global variable. The other Entry widgets potentially have the same problem, so in the code below I have declared all of them global.

I also noticed another potential issue you're likely to run into, namely assigning the return value of the grid() method to a variable. e.g.:

Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)

This is not doing what you think because the grid() method always returns None, so that's the value that's getting assigned to Book. I haven't fixed these, but doing so is easy, just create the widget first and assign it to a variable, and then on another line, all variable.grid(...).

One final piece of advice: read and start following the PEP 8 - Style Guide for Python Code. I've done that to some degree to the version of your code with the fix in it shown below.

FYI: The accepted answer to the question Best way to structure a tkinter application describes an excellent object-oriented way to structure and implement Tkinter-based applications.

from tkinter import *


def book_harvard():
    global author_entry, year_entry, title_entry  # ADDED

    reference = author_entry.get()
    reference_1 = year_entry.get()
    reference_2 = title_entry.get()
    string_to_display = reference + reference_1 + reference_2
    print(string_to_display)


def TypeofTextHarvard():
    second = Toplevel(first)
    first.withdraw()
    second.title("Type of Source")
    Source = Label(second, text = "What type of source would you like to reference?").grid(column=1, row=0)
    Book = Button(second, text="Book", command=Harvard).grid(column=1, row=1)
    Chapter = Button(second, text="Book Chapter").grid(column=1, row=2)
    Journal = Button(second, text="Journal Article").grid(column=1, row=3)


first = Tk()
first.title("Referencing Style")
Reference = Label(first, text="Which referencing style would you like to use?").grid(column=1, row=0)
Harvard = Button(first, text="Harvard Style", command=TypeofTextHarvard).grid(column=1, row=1)
APA = Button(first, text="APA Style").grid(column=1, row=2)


def Harvard():
    global author_entry, year_entry, title_entry  # ADDED

    third = Toplevel()
    third.title("book")
    author = StringVar()
    year = StringVar()
    title = StringVar()

    author_label = Label(third, text="Author")
    author_entry = Entry(third)
    year_label = Label(third, text="Year")
    year_entry = Entry(third)
    title_label = Label(third, text="Title")
    title_entry = Entry(third)
    button_1 = Button(third, text="Done", command=book_harvard)
    author_label_2 = Label(third, textvariable=author)
    year_label_2 = Label(third, textvariable=year)
    title_label_2 = Label(third, textvariable=title)

    author_label.grid(row=0, column=0)
    author_entry.grid(row=0, column=1)
    year_label.grid(row=1, column=0)
    year_entry.grid(row=1, column=1)
    title_label.grid(row=2, column=0)
    title_entry.grid(row=2, column=1)
    button_1.grid(row=3, column=0)
    author_label_2.grid(row=4, column=1)
    year_label_2.grid(row=4, column=2)
    title_label_2.grid(row=4, column=3)


first.mainloop()
martineau
  • 119,623
  • 25
  • 170
  • 301