How to fix this error of python tkinter StringVar? - python

So basically i am going to write a program of python tkinter to show weight, however the variables and the objects are distracting me.
My code is like this:
from tkinter import *
import tkinter as tk
#object oriented BMI project
class Root(Tk):
def __init__(self):
super(Root, self).__init__()
#Info Bar
self.title("Shushu BMI Calculator")
self.geometry("1100x600")
#self.resizable("False")
#var
self.weight = tk.StringVar()
#self.w = tk.StringVar()
#Caption
self.caption = tk.Label(text = "BMI Calculator - Beta 2.0",
fg = "brown",
font="Arial 40")
self.caption.grid(column = 0, row = 0, sticky = "N")
#Copyright
self.copyright = tk.Label(text = "Powered by Shushu Studio",
fg = "green",
font = "Arial 20")
self.copyright.grid(column = 1, row = 0, sticky = "E")
#Weight input Row
self.weightInputTag = tk.Label(text="Please input your weight here (kg)")
self.weightInputTag.grid(column = 0, row = 1, sticky = "W")
self.weightEntry = tk.Entry(textvariable = self.weight)
self.weightEntry.grid(column = 0, row = 1)
self.weightSubmit = tk.Button(text="Submit",
COMMAND=self.weightget)
self.weightSubmit.grid(column = 0, row = 2)
self.showWeight = tk.Label(text="")
self.showWeight.grid(column = 0, row = 3)
def weightget(self):
weight = self.weightEntry.get()
self.showWeight.configure(text=weight)
root = Root()
root.mainloop()
And the console show this:
Resetting Python state.
Running P:\2020\09\25\bmi.py
The interactive Python process has exited.
Traceback (most recent call last):
File "P:\2020\09\25\bmi.py", line 52, in <module>
root = Root()
File "P:\2020\09\25\bmi.py", line 41, in __init__
COMMAND=self.weightget)
File "P:\Language\lib\tkinter\__init__.py", line 2345, in __getattr__
return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'weightget'
Please help, thanks very much!

The indention of your function was wrong.
def weightget(self):
weight = self.weightEntry.get()
self.showWeight.configure(text=weight)
If you want this function working as class method and not as a normal function in your local namespace of your class. Which I assume, since you put the parameter self in the function, then you need to make sure its on the right spot by the indentation.
import tkinter as tk
class Root(tk.Tk):
def __init__(self):
super(Root, self).__init__()
#Info Bar
self.title("Shushu BMI Calculator")
self.geometry("1100x600")
#self.resizable("False")
#var
self.weight = tk.StringVar()
#self.w = tk.StringVar()
#Caption
self.caption = tk.Label(text = "BMI Calculator - Beta 2.0",
fg = "brown",
font="Arial 40")
self.caption.grid(column = 0, row = 0, sticky = "N")
#Copyright
self.copyright = tk.Label(text = "Powered by Shushu Studio",
fg = "green",
font = "Arial 20")
self.copyright.grid(column = 1, row = 0, sticky = "E")
#Weight input Row
self.weightInputTag = tk.Label(text="Please input your weight here (kg)")
self.weightInputTag.grid(column = 0, row = 1, sticky = "W")
self.weightEntry = tk.Entry(textvariable = self.weight)
self.weightEntry.grid(column = 0, row = 1)
self.weightSubmit = tk.Button(self,text="Submit",
command=self.weightget)
self.weightSubmit.grid(column = 0, row = 2)
self.showWeight = tk.Label(text="")
self.showWeight.grid(column = 0, row = 3)
def weightget(self):
weight = self.weightEntry.get()
self.showWeight.configure(text=weight)
root = Root()
root.mainloop()

from tkinter import *
import tkinter as tk
#object oriented BMI project
class Root(Tk):
def __init__(self):
super(Root, self).__init__()
def weightget(self):
weight = self.weightEntry.get()
self.showWeight.configure(text=weight)
#Info Bar
self.title("Shushu BMI Calculator")
self.geometry("1100x600")
#self.resizable("False")
#var
self.weight = tk.StringVar()
#self.w = tk.StringVar()
#Caption
self.caption = tk.Label(text = "BMI Calculator - Beta 2.0",
fg = "brown",
font="Arial 40")
self.caption.grid(column = 0, row = 0, sticky = "N")
#Copyright
self.copyright = tk.Label(text = "Powered by Shushu Studio",
fg = "green",
font = "Arial 20")
self.copyright.grid(column = 1, row = 0, sticky = "E")
#Weight input Row
self.weightInputTag = tk.Label(text="Please input your weight here (kg)")
self.weightInputTag.grid(column = 0, row = 1, sticky = "W")
self.weightEntry = tk.Entry(textvariable = self.weight)
self.weightEntry.grid(column = 0, row = 1)
self.weightSubmit = tk.Button(text="Submit", command=lambda:weightget(self))
self.weightSubmit.grid(column = 0, row = 2)
self.showWeight = tk.Label(text="")
self.showWeight.grid(column = 0, row = 3)
root = Root()
root.mainloop()
This works properly. Define the function before the process.
self.weightSubmit = tk.Button(text="Submit", command=lambda:weightget(self))
Give the command for the button like this as you are using object oriented programming. Make sure to use lambda
Read this https://www.w3schools.com/python/python_lambda.asp and you will get a better understanding about lambda

Related

Tkinter: keep update a variable

I really need help, my brain is melting because of this problem. I've studied python for 2 months maybe and I'm not very expert in programming. I've got an issue... I'm using tkinter on this program; in this small GUI I'd like to always keep updated the global variable "temp", and its value should change everytime I click on the button. I know that mainloop() is a blocking method, so it is possible to do something like this?
import tkinter as tk
class App:
def __init__(self):
super().__init__()
self.screen = tk.Tk()
self.screen.geometry("400x400")
self.screen.title("Modifica temperatura ambiente")
self.screen.grid_columnconfigure(0, weight = 1)
self.label = tk.Label(self.screen, text="ENTER TEMPERATUR VALUE", fg = "black", font = ("Calibri", 10) )
self.label.grid(row = 0, column = 0, sticky = "N", pady = 10)
self.input_ = tk.Entry(self.screen)
self.input_.grid(row = 1, column = 0, sticky = "WE", pady = 5, padx = 20)
self.button = tk.Button(self.screen, text = "INVIA", command = self.getvalue)
self.button.grid(row = 2, column = 0, sticky = "WE", pady = 5, padx = 10)
def getvalue(self):
self.temp = self.input_.get()
temperatura_label = tk.Label(self.screen, text = "Last input value is " + self.temp + " degrees", fg = "red")
temperatura_label.grid(row = 3, column = 0, sticky = "S")
return self.temp
app = App()
temp = app.getvalue()
print(temp)
app.screen.mainloop()
Thank for the help!
If you want to print it in the terminal, modify your getvalue function.
Code:
import tkinter as tk
screen = tk.Tk()
screen.geometry("400x400")
screen.title("Modifica temperatura ambiente")
screen.grid_columnconfigure(0, weight = 1)
class App:
def __init__(self, master):
super().__init__()
self.master = master
self.label = tk.Label(master, text="ENTER TEMPERATUR VALUE", fg = "black", font = ("Calibri", 10) )
self.label.grid(row = 0, column = 0, sticky = "N", pady = 10)
self.input_ = tk.Entry(master)
self.input_.grid(row = 1, column = 0, sticky = "WE", pady = 5, padx = 20)
def getvalue(self):
self.temp = self.input_.get()
temperatura_label = tk.Label(self.master, text = "Last input value is " + self.temp + " degrees", fg = "red")
temperatura_label.grid(row = 3, column = 0, sticky = "S")
if self.temp == None:
print()
else:
return self.temp
app = App(screen)
def main_loop():
global app
temp = app.getvalue()
print(temp)
button = tk.Button(screen, text = "INVIA", command = main_loop)
button.grid(row = 2, column = 0, sticky = "WE", pady = 5, padx = 10)
screen.mainloop()

AttributeError: 'Vocabulary' object has no attribute 'listBox'

I am creating Vocabulary, a GUI program to manage unknown words. I am getting:
/usr/bin/python3.5 /home/cali/PycharmProjects/Vocabulary/Vocabulary.py
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/init.py", line 1553, in call
return self.func(*args) File "/home/cali/PycharmProjects/Vocabulary/Vocabulary.py", line 86, in
add_item
self.listBox.insert(END, self.get_word()) AttributeError: 'Vocabulary' object has no attribute 'listBox'
Process finished with exit code 0
... when I try to add an item to the listbox.
Here is what I have done:
#!/usr/bin/env python
# Vocabulary.py
# GUI program to manage unknown words
from tkinter import *
class Word:
def __init__(self, wordorphrase, explanation, translation, example):
self.wordorphrase = wordorphrase
self.explanation = explanation
self.translation = translation
self.example = example
class Vocabulary(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.master.resizable(width = False, height = False)
self.master.title("Vocabulary")
self.create_widgets()
def create_widgets(self):
lblWordsOrPhrases = Label(self.master, text = 'Words or Phrases:')
lblWordsOrPhrases.grid(row = 0, column = 0)
lblWordOrPhrase = Label(self.master, text = 'Word or phrase:')
lblWordOrPhrase.grid(row = 0, column = 1, sticky = W)
listBox = Listbox(self.master,
height = 34,
width = 30)
listBox.grid(row = 1, column = 0, rowspan = 7)
txt_WordOrPhrase = Text(self.master,
height = 1,
width = 40)
txt_WordOrPhrase.grid(row = 1, column = 1, sticky = N)
lblExplanation = Label(self.master, text = 'Explanation:')
lblExplanation.grid(row = 2, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 3, column = 1, sticky = N)
lblTranslation = Label(self.master, text = 'Translation:')
lblTranslation.grid(row = 4, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 5, column = 1, sticky = N)
lblExamples = Label(self.master, text = 'Example(s):')
lblExamples.grid(row = 6, column = 1, sticky = W)
txt_Explanation = Text(self.master,
height = 10,
width = 40)
txt_Explanation.grid(row = 7, column = 1, sticky = S)
btn_Add = Button(self.master,
text = 'Add',
command = self.add_item)
btn_Add.grid(row = 8, column = 0, sticky = W)
def get_word(self):
return self.txt_WordOrPhrase.get('1.0', '1.0 lineend')
def get_explanation(self):
return self.txt_Explanation.get('1.0', '1.0 lineend')
def get_translation(self):
return self.txt_Translation.get('1.0', '1.0 lineend')
def get_example(self):
return self.txt_Example.get('1.0', '1.0 lineend')
def add_item(self):
self.listBox.insert(END, self.get_word())
def main():
root = Tk()
Vocabulary(root)
root.mainloop()
if __name__ == '__main__':
main()
I'm using Python 3.5.
You listbox is a variable local to create_widgets since it is not set with self. In order to make the variable available instance-wide, you need to contain it in self.
Change the line in create_widgets to self.listBox = Listbox(self.master, height = 34, width = 30) and change every reference to listBox to self.listBox in order to apply this change.
You might want to defined self.listBox in __init__(), as it might help keep track of instance variables.

Error with tkinter class [duplicate]

This question already has an answer here:
Why do my Tkinter widgets get stored as None? [duplicate]
(1 answer)
Closed 6 years ago.
I am making a basic temperture converter, I have it so you can convert celcius to farenheight, and now im trying to make it so you can switch. I have this code:
from tkinter import *
bool1 = True
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.x = Label(frame, text = 'Celcius:').grid(row = 0, column = 0)
self.c_var = DoubleVar()
Entry(frame, textvariable = self.c_var).grid(row = 0, column = 1)
self.z = Label(frame, text = 'Farenheight:').grid(row = 1, column = 0)
self.result_var = DoubleVar()
Label(frame, textvariable = self.result_var).grid(row = 1, column = 1)
b1 = Button(frame, text = 'Switch', command = self.switch)
b1.grid(row = 2, columnspan = 2)
button = Button(frame, text = 'Convert', command = self.convert)
button.grid(row = 3, columnspan = 2)
return None
def convert(self):
c = self.c_var.get()
c = c * (9/5) + 32
self.result_var.set(c)
def switch(self):
global bool1
if bool1 == True:
bool1 = False
self.x.config(text = 'Farenheight:')
else:
bool1 = True
self.z['text'] = 'Celcius:'
root = Tk()
root.wm_title('Temp Converter')
app = App(root)
root.mainloop()
The error message I am getting is:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\keith\AppData\Local\Programs\Python\Python35- 32\lib\tkinter\__init__.py", line 1550, in __call__
return self.func(*args)
File "C:\Users\keith\Desktop\tkinter.py", line 26, in switch
self.x.config(text = 'Farenheight:')
AttributeError: 'NoneType' object has no attribute 'config'
The problem comes from the fact that you assigned the x and z attributes (self.x, self.z) not to the tkinter labels but to whatever the Tkinter.Label.grid() function returns, which is None.
Instead, separate the declaration of the label and their grid configuration onto two lines that first declares the variables and then calls the grid function on them, thereby assigning x and z to the labels themselves.
from tkinter import *
bool1 = True
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.x = Label(frame, text = 'Celcius:')
self.x.grid(row = 0, column = 0)
self.c_var = DoubleVar()
Entry(frame, textvariable = self.c_var).grid(row = 0, column = 1)
self.z = Label(frame, text = 'Farenheight:')
self.z.grid(row = 1, column = 0)
self.result_var = DoubleVar()
Label(frame, textvariable = self.result_var).grid(row = 1, column = 1)
b1 = Button(frame, text = 'Switch', command = self.switch)
b1.grid(row = 2, columnspan = 2)
button = Button(frame, text = 'Convert', command = self.convert)
button.grid(row = 3, columnspan = 2)
return None
def convert(self):
c = self.c_var.get()
c = c * (9/5) + 32
self.result_var.set(c)
def switch(self):
global bool1
if bool1 == True:
bool1 = False
self.x.config(text = 'Farenheight:')
else:
bool1 = True
self.z['text'] = 'Celcius:'
root = Tk()
root.wm_title('Temp Converter')
app = App(root)
root.mainloop()

Tkinter - Making Program Wait for User Input

I have a program that calculates a persons BMI after the user gives his height and weight.
I used variable.insert() to insert a value so the program doesn't have errors.
Is there any way to have the program start 'empty' without getting errors? Basically, I need it to not do anything until the calculate button is pressed.
from Tkinter import *
class App(Tk):
def __init__(self):
Tk.__init__(self)
self.height()
self.weigh()
self.output()
self.calculate()
def height(self):
Label(self, text = "Enter Height, feet").grid()
self.feet = Entry(self)
self.feet.grid(row = 0, column = 1)
self.feet.insert(0, "1")
Label(self, text = "Enter Height, inches").grid(row = 1, column = 0)
self.inches = Entry(self)
self.inches.grid(row = 1, column = 1)
self.inches.insert(0, "1")
def weigh(self):
Label(self, text = "Enter Weight").grid(row =2, column = 0)
self.weight = Entry(self)
self.weight.grid(row = 2, column = 1)
self.weight.insert(0, "1")
def output(self):
self.calcBMI = Button(self, text = "Calculate BMI")
self.calcBMI.grid(row = 6, columnspan = 2)
self.calcBMI["command"] = self.calculate
Label(self, text = "Body Mass Index").grid(row = 4, column = 0)
self.lblbmi = Label(self, bg = "#fff", anchor = "w", relief = "groove")
self.lblbmi.grid(row = 4, column = 1, sticky = "we")
Label(self, text = "Status").grid(row = 5, column = 0)
self.lblstat = Label(self, bg = "#fff", anchor = "w", relief = "groove")
self.lblstat.grid(row = 5, column = 1, sticky = "we")
def calculate(self):
ft = int(self.feet.get())
inch = int(self.inches.get())
ht = ft * 12 + inch
wt = int(self.weight.get())
bmi = (wt * 703) / (ht ** 2)
self.lblbmi["text"] = "%.2f" % bmi
if bmi > 30:
self.lblstat["text"] = "Obese"
elif bmi > 25:
self.lblstat["text"] = "Overweight"
elif bmi > 18.5:
self.lblstat["text"] = "Normal"
else:
self.lblstat["text"] = "Underweight"
def main():
app = App()
app.mainloop()
if __name__ == "__main__":
main()
What you are doing right now is calling the output outright(& also by pressing the calculate button). What you need to do is call it only when the button is pressed
From init() remove self.calculate().
Now just remove all the insert statements. You don't need them anymore ;)
Edit:
As Joe suggested in his comment, you could also disable the button until all the fields are populated. You could do this by setting its state to disabled,like this:
self.calcBMI.config(state='disabled')

Python - Tkinter empty window

I'm doing an assignment for a course and I'm not really sure what's up with the code but it runs without error, only displaying an empty window. I used an example given as a start and basically modified it to get this code. If needed I can provide the example code to compare.
from Tkinter import *
class App(Tk):
def __init(self):
Tk.__init__(self)
self.height()
self.weigh()
self.calculate()
self.output()
def height(self):
Label(self, text = "Enter Height, feet").grid()
self.feet = Entry(self)
self.feet.grid(row = 0, column = 1)
self.feet.insert(0, "100")
lblinches = Label(self, text = "Enter Height, inches")
lblinches.grid(row = 1, column = 0)
self.inches = Entry(self)
self.inches.grid(row = 1, column = 1)
def weigh(self):
Label(self, text = "Enter Weight").grid(row =2, column = 0)
self.weight = Entry(self)
self.weight.grid(row = 2, column = 1)
def output(self):
self.calcBMI = Button(self, text = "Calculate BMI")
self.calcBMI.grid()
self.calcBMI["command"] = self.calculate
Label(self, text = "Body Mass Index").grid(row = 4)
Label(self, text = "Status").grid(row = 5)
def calculate(self):
feet1 = int(self.feet.get())
inches1 = int(self.inches.get())
height1 = feet1 *12 + inches1
weight1 = int(self.weight.get())
bmi = (weight1 * 703) / (height1 * 2)
self.lblbmi["text"] = ".2f" % bmi
def main():
app = App()
app.mainloop()
main()
__init should be __init__. Since __init__ was not defined, none of the configuration methods were called.

Categories