Python Tkinter: AttributeError: Checkbutton instance has no attribute 'get' - python

I am new to Tkinter. I am trying to create a GUI that has two spinboxes and two checkboxes whose values will be printed when a user clicks a particular button ("Start"). Here is my code so far:
from Tkinter import *
from tkFileDialog import askopenfilename
from PIL import Image
#create TK frame
root = Tk()
#identify the dimensions of the TK frame
root.geometry("360x150")
#title the TK frame
root.title("Literature Online API")
#create a function that will return the filepath for a file provided by the user
def selectfile():
user_defined_filepath['filename'] = askopenfilename(filetypes=[("Text","*.txt")]) # user_defined_filepath['filename'] may now be accessed in the global scope.
#create a function that will allow the "start" button to begin further processes
def startapi(event = "<Button>"):
print windowlengthspinbox.get()
print slideintervalspinbox.get()
print fuzzyspellingbutton.get()
print lemmatizedsearchbutton.get()
#create variables for the checkbuttons -- default = 0, checked = 1
fuzzyspellingvariable = IntVar()
lemmatizedsearchvariable = IntVar()
#create a caption that will appear as the first line of the grid
firstlinelabel = Label(root, text = "Please select any desired search options:")
firstlinelabel.grid(row = 0, column = 0, sticky = W)
#create a button that allows users to employ Literature Online's fuzzy spelling feature. Add the object.grid() method on new line because appending .grid() to the line in which one defines object causes Python to give the object attribute "NoneType." http://stackoverflow.com/questions/1101750/python-tkinter-attributeerror-nonetype-object-has-no-attribute-get
fuzzyspellingbutton = Checkbutton(root, text="Fuzzy Spelling", variable=fuzzyspellingvariable)
fuzzyspellingbutton.grid(row = 1, column = 0, sticky = W)
#create a button that allows users to employ Literature Online's lemmatized search feature
lemmatizedsearchbutton = Checkbutton(root, text="Lemmatized Search", variable=lemmatizedsearchvariable)
lemmatizedsearchbutton.grid(row = 2, column = 0, sticky = W)
#create a spinbox that allows users to identify desired window length
windowlengthspinbox = Spinbox(root, from_=1, to=10)
windowlengthspinbox.grid(row = 3, column = 1, sticky = W)
windowlengthspinboxlabel = Label(root, text = "Please select window size")
windowlengthspinboxlabel.grid(row = 3, column = 0, sticky = W)
#create a spinbox that allows users to identify desired window length
slideintervalspinbox = Spinbox(root, from_=1, to=10)
slideintervalspinbox.grid(row = 4, column = 1, sticky = W)
slideintervalspinboxlabel = Label(root, text = "Please select window slide interval")
slideintervalspinboxlabel.grid(row = 4, column = 0, sticky = W)
#create a button that allows users to find a file for analysis
selectfilebutton = Button(root,text="Select File",command=selectfile)
selectfilebutton.grid(row = 5, column = 0, sticky = W)
#create a start button that allows users to submit selected parameters and file
startbutton = Button(root, text="Start", command = startapi, width = 8)
startbutton.grid(row = 5, column = 1, sticky = E)
startbutton.bind("<Button>", startapi)
#startbutton.focus()
#instantiate the Tk window
root.mainloop()
When I click the "Start" button, the GUI prints the values of the spinboxes, then tells me that Checkbutton instance has no attribute 'get':
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "groundupgui.py", line 20, in startapi
print fuzzyspellingbutton.get()
AttributeError: Checkbutton instance has no attribute 'get'
Does anyone know how I can print the values of the checkboxes? I would be grateful for any suggestions or insight.

To find the state of the Checkbutton use the fuzzyspellingvariable that you've attached to the Checkbutton:
fuzzyspellingvariable.get()
By the way, since the checkbutton only has two states, you could use a BooleanVar instead of an IntVar here:
fuzzyspellingvariable = BooleanVar()

Ah, I got it. You need to perform the .get() method on the variable, not the button:
print fuzzyspellingvariable.get()
print lemmatizedsearchvariable.get()

Related

How to bind a mouse click with a tkinter witdges? [duplicate]

This question already has answers here:
Entry box text clear when pressed Tkinter
(2 answers)
Closed 2 years ago.
I want to clear text box as soon as i click on it to write, Please help me to do this
from tkinter import *
from tkinter import ttk
root = Tk()
fileLable = Text(root, height = 1, width = 26 )
fileLable.insert(INSERT, "this text")
fileLable.grid(row = 0, column = 0,columnspan = 2, padx = (10,0),pady = (3,0))
submit = ttk.Button(root, text = "Submit", command = some_method)
submit.grid(row = 1, column = 1, padx = (10,0), pady = (10,0))
root.mainloop()
I know that this one :
def some_callback(event): # note that you must include the event as an arg, even if you don't use it.
e.delete(0, "end")
return None
So then how I catch this event when it is clicked on the text box to include above code to my main code
Please help thanks in advance 😊
You could try this below, bind events <FocusIn> and <FocusOut>:
from tkinter import *
from tkinter import ttk
def delText(event=None):
fileLable.delete("1.0", END)
root = Tk()
fileLable = Text(root, height = 1, width = 26 )
fileLable.insert(INSERT, "this text")
fileLable.grid(row = 0, column = 0,columnspan = 2, padx = (10,0),pady = (3,0))
fileLable.bind("<FocusIn>", delText)
submit = ttk.Button(root, text = "Submit")
submit.grid(row = 1, column = 1, padx = (10,0), pady = (10,0))
root.mainloop()
To call a function when a user clicks in a widget, you can bind to the <1> event. The function is passed an argument which contains information about the event, including a reference to the widget that received the event.
To delete all of the text in a text widget, call the delete method with the arguments "1.0" and "end".
Putting that together, it looks like this:
def clearText(event):
event.widget.delete("1.0", "end")
fileLable.bind("<1>", clearText)

Chechboxes in Tkinter

I'm new to GUIs, and I'm writing some code segments for school. This is an issue I've been having in multiple assignments and I can't seem to wrap my head around it. When I implement checkboxes, the value returned is always positive regardless of whether or not I check to box. For example, this is a code I've been writing that is supposed to create a menu for the user to select from, and them display the correct total:
from tkinter import *
def main():
class Application(Frame):
#GUI application that creates a menu to be chosen from and selections to be made.
def __init__(self, master):
#Initialize Frame.
Frame.__init__(self, master)
self.grid()
self.createWidgets()
def addPrices(self):
#store price float
price = 0.00
#add all contents of the list selected
#use if statement to determine which prices need to be added
if self.isPizza:
price += 3.00
if self.isFries:
price += 0.50
if self.isCoke:
price += 0.25
if self.isChurro:
price += 1.50
#display totals
#Use label to print total
Label(self,text = "Your total is: ").grid(row = 9, column = 0, columnspan = 2, sticky = W)
Label(self,text = price).grid(row = 10, column = 0, columnspan = 2, sticky = W)
def createWidgets(self):
#create instruction label
Label(self,text = "Please Select your Items:").grid(row = 0, column = 4, columnspan = 2, sticky = W)
#create labels for checkboxes / menu
Label(self,text = "Pizza.... $3.00").grid(row = 1, column = 5, sticky = W)
Label(self,text = "Fries... $0.50").grid(row = 2, column = 5, sticky = W)
Label(self,text = "Coke... $0.25").grid(row = 3, column = 5, sticky = W)
Label(self,text = "Churro... $1.50").grid(row = 4, column = 5, sticky = W)
#create input via checkboxes
#Create a plain of checkboxes to select items
self.isPizza = BooleanVar()
Checkbutton(self,text = "Pizza",variable = self.isPizza).grid(row = 6, column = 0, sticky = W)
self.isFries = BooleanVar()
Checkbutton(self, text = "Fries",variable = self.isFries).grid(row = 6, column = 1, sticky = W)
self.isCoke = BooleanVar()
Checkbutton(self, text = "Coke",variable = self.isCoke).grid(row = 7, column = 0, sticky = W)
self.isChurro = BooleanVar()
Checkbutton(self, text = "Churro",variable = self.isChurro).grid(row = 7, column = 1, sticky = W)
#Create submit button
Button(self,text = "Click to submit order",command = self.addPrices).grid(row = 8, column = 0, sticky = W)
root = Tk()
root.geometry("800x400")
root.title(" Order Up!")
app = Application(root)
root.mainloop()
main()
The program always returns 5.25 as the total, which is just the amount of all items added together. Am I missing a segments that will change my Boolean variables depending on user input?
You need to test the boolean value of the each Var's value, not of the Var itself.
Change if self.isPizza: to if self.isPizza.get():, etc, and your program works.
PS Wrapping your entire program in def main: and calling main(), as you did, is useless and wastes an indentation level and makes the program harder to read. If you want to make a file useful for import, as well as direct running, define your top-level classes and functions as module level and only put code that does things that should not happen on import inside main, and then guard the execution of main. In this case:
from tkinter import *
class Application:
...
def main():
root = Tk()
...
root.mainloop()
if __name__ == '__main__':
main()
You can now import this file into a test file and test the Application class without root.mainloop() taking control.

Change tkinter entry widget multiple times after pressing a button

I have a tkinter Entry widget and when a user presses a button the contents update:
from tkinter import *
window = Tk()
def abcdef(num):
ent.config(state=NORMAL)
ent.delete(0, 'end')
ent.insert(0, num)
ent.config(state = "readonly")
print(num) #Just to check the code is being run
def changeEntry():
for j in range(3):
ent.after(1000, abcdef(j))
ent = Entry(widow, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")
btn = Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)
window.mainloop()
When I press the button the window freezes for 3 seconds and then just displays the final number. How can I make it so when the user presses the button, the entry changes every second instead of just freezing for 3 seconds and only displaying the final one?
Thanks in advance
You have two problems with that .after call. The .after method tells Tkinter to call the function you pass it after the time interval has passed. But you're telling Tkinter to do 3 things after 1000 milliseconds have passed, so they'll all happen on top of each other. So you need to stagger the delays.
Secondly, you need to give .after a function to call when its time to call it. But your code calls the function and gives .after the return value of your function. We can fix that by wrapping the function call inside another function. A convenient way to do that is using lambda, giving the lambda a default argument it can pass to abcdef
import tkinter as tk
window = tk.Tk()
def abcdef(num):
ent.config(state=tk.NORMAL)
ent.delete(0, 'end')
ent.insert(0, num)
ent.config(state = "readonly")
print(num) #Just to check the code is being run
def changeEntry():
for j in range(3):
ent.after(1000 * j, lambda num=j: abcdef(num))
ent = tk.Entry(window, text="", state = "readonly", readonlybackground="white", font = "20")
ent.grid(row = 0, column = 0, columnspan = 3, sticky = "E")
btn = tk.Button(window, text="Button", command=changeEntry)
btn.grid(row = 1, column = 0, sticky = "NESW", pady = 10, padx = 10)
window.mainloop()
I've also replaced that "star" import with the neater import tkinter as tk. That makes it obvious which names come from Tkinter and which names are local to your program.
Bryan Oakley points out that we don't need that lambda, we can pass in arguments after the function name. See the Basic Widget Methods in the Tkinter docs for details. So we can re-write changeEntry like this:
def changeEntry():
for j in range(3):
ent.after(1000 * j, abcdef, j)
Thanks, Bryan!

Working with GUIs and text files - how do I 'synchronize' them?

I am working on a larger programming project, and since I am a beginner it is not that complex. I will try to keep it straight forward: I want to create a GUI program that reads from a text file with "elements of notes", i.e. as a calendar.
The interface should have "text entry box", where you can submit new notes, and there should also be two buttons that upon pressing them "scrolls" up and down among the existing notes, i.d. turning page. A single note should be displayed at all times in a text box under the two buttons.
So, to wrap this up, my question is: How is the best way to "load" the text file's notes to the program, so that I can make the buttons scroll between them? Should I read the text file into a list that I give my Application(Frame) object?
Here is some of my code so far:
from tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self, master):
""" Initialize Frame. """
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2 column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
# main
text_file = open("diary.txt", "r")
note_list = text_file.readlines()
text_file.close()
# No idea where to put the note_list, which 'client' should receive it?
root = Tk()
root.title("Diary")
app = Application(root)
root.mainloop()
So now that you have examined my code, how to fill in the missing pieces?
Edit: I added the text_file and note_list under the # main.
Note: I have used calendar and diary interchangeably, but the program is more of a calendar.
You can use it inside Application class:
from Tkinter import *
class Application(Frame):
""" GUI application that creates diary. """
def __init__(self):
""" Initialize Frame. """
Frame.__init__(self)
self.note_list = []
with open("diary.txt", "r") as notes:
self.note_list = text_file.readlines()
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get info of choices and display notes. """
# create a label and text entry for new note
Label(self,
text = "Enter new note:"
).grid(row = 1, column = 0, sticky = W)
self.note_ent = Entry(self)
self.note_ent.grid(row = 1, column = 1, sticky = W)
# create a submit button for the new note
Button(self,
text = "Submit",
# command = self.add_note to a list within app obeject?
).grid(row = 2, column = 0, sticky = W)
# create a 'next note' button
Button(self,
text = "Next",
# command = self.next_note which goes to a list?
).grid(row = 6, column = 0, sticky = W)
# create a 'past note' button
Button(self,
text = "Back",
# command = self_past_note, or should I reuse next_note?
).grid(row = 6, column = 0, sticky = W)
# create a textbox (I am not sure?)
self.show_ent = Text(self, width = 75, height = 10, wrap = WORD)
self.show_ent.grid(row = 7, column = 0, columnspan = 4)
app = Application()
app.master.title("Diary")
app.mainloop()

Python Tkinter not opening when using .grid()

I am working through online tutorials to learn how to make a GUI with Tkinter. But i am having an issue when using the .grid() function.
Here is what i have so far:
from Tkinter import *
root = Tk()
title = Label(root, text = "Hello World")
title.pack()
name = Label(root, text = "Name")
password = Label(root, text = "Password")
entry_name = Entry(root)
entry_password = Entry(root)
name.grid (row = 0, sticky = E)
password.grid (row = 0, sticky = E)
entry_name.grid (row = 0, column = 1)
entry_password.grid (row = 1, column = 1)
check = Checkbutton(root, text = "Keep me logged in")
check.grid(columnspan = 2)
root.mainloop()
So the problem im having is as soon as i include that first line:
name.grid(row = 0, sticky = E)
And then run the script, there are no errors, but nothing opens. The program just hangs and i have to close the command prompt in order to regain control.
If i comment out all the lines using .grid() they program works fine and will open a window with my title inside it.
So, does anyone know what im doing wrong?
Im using Python 2.7
You cannot use both pack and grid with two or more widgets that share the same parent. In your case you're using pack for title and grid for everything else. Use one or the other.
Keep grid geometry manager consistent so use title.grid().
from tkinter import *
root = Tk()
title = Label(root, text = "Hello World")
title.grid()
name = Label(root, text = "Name")
password = Label(root, text = "Password")
entry_name = Entry(root)
entry_password = Entry(root)
name.grid(row = 0, sticky = E)
password.grid (row = 0, sticky = E)
entry_name.grid (row = 0, column = 1)
entry_password.grid (row = 1, column = 1)
check = Checkbutton(root, text = "Keep me logged in")
check.grid(columnspan = 2)
root.mainloop()

Categories

Resources