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()
Related
I am using Tkinter in Python 3 to create a converter between hex, binary and denary - while creating my own methods for conversions instead of using the built in methods.
I've completed the denary to binary conversion through the use of my 'highestPowerOf2' method in the DenToBin class. I want to use this method in my HexToBin class, but whenever I try to, an additional blank window pops up and I receive - AttributeError: 'NoneType' object has no attribute 'title' - error.
How would I run 'highestPowerOf2' in the HexToBin class?
(also sorry for any poor programming practise)
Code:
from tkinter import *
from functools import partial
class Menu(Frame):
def __init__(self, master= None): # initialise Menu
Frame.__init__(self, master) # initialise Frame
self.master = master # what does this do
self.createWindow()
def createWindow(self):
self.pack(fill = BOTH, expand = 1)
denToBin = Button(self, text = 'Denary to Binary', command = lambda: self.changeWindow(DenToBin))
denToBin.pack(fill = X, padx = 10, pady = 10)
hexToBin = Button(self, text = 'Hex to Binary', command = lambda: self.changeWindow(HexToBin))
hexToBin.pack(fill = X, padx = 10, pady = 10)
def changeWindow(self, object):
root.withdraw()
currentFrame = object(root)
class DenToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
# print(self.denary) -- Why is this not recognised?????????
self.master.title('Unit Converter: Denary to Binary')
instructionDen = Label(self, text = 'Denary Value: ')
instructionDen.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.denaryEntry = Entry(self)
self.denaryEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = lambda: self.highestPowerOf2(10)) # as an example
convertButton.grid(row = 3, column = 1)
# finds highest power of 2 that is less than denary number - helps self.convert()
def highestPowerOf2(self,number):
print('I find the highest power of 2 that fits into the number given.')
class HexToBin(Toplevel):
def __init__(self, master = None):
Toplevel.__init__(self, master)
self.master = master
self.Window()
self.denary = 0
def Window(self):
self.master.title('Unit Converter: Hexadecimal to Binary')
instructionHex = Label(self, text = 'Hexadecimal Value: ')
instructionHex.grid(row = 1, column = 0, padx = 10)
instructionBin = Label(self, text = 'Binary Value: ')
instructionBin.grid(row = 2, column = 0, padx = 10)
self.hexadecimalEntry = Entry(self)
self.hexadecimalEntry.grid(row = 1, column = 2, padx = 10, pady = 5)
convertButton = Button(self, text = 'Convert!', command = self.convert)
convertButton.grid(row = 3, column = 1)
def convert(self):
# I need to call the 'highestPowerOf2' method here.
pass
root = Tk()
unitConverter = Menu(root) # root is master
root.mainloop()
I was really curious why I cannot get my add_button to work,
as the window fails to come up when creating it.
from tkinter import *
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = 0
self.input2 = 0
input1 = Entry(master)
input2 = Entry(master)
input1.grid(row = 0, column = 1)
input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_buton = Button(master, text = "Add", command = self.add())
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
return self.input1.get() + self.input2.get()
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
#-------------------------------------------------
Welcome to Stack!
I've looked through you code I've been able to do what you are asking. There were a few errors within your code:
a) you had self.add_buton and self.add_button which caused an error.
b) self.input1 = 0 and self.input2 = 0 are not required.
c) You were calling self.add() as the command and you should be calling self.add. When calling it as a command you do not need ()
d)input1 = Entry(master) should be self.input1 = tk.Entry(master)
e) You should convert your input values into int or float as otherwise it will just one value onto the end of the other. (Eg, 1 + 5 = 15 whereas int(1) + int(5) = 6
Here is your code with the entry boxes working as they should. I have import tkinter as tk hence why it is tk.Entry
from tkinter import *
import tkinter as tk
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input2 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input1.grid(row = 0, column = 1)
self.input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_button = tk.Button(master, text = "Add", command = self.add)
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
val = self.input1.get()
print(val)
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
This should now work how you wanted it too. The variables within the entry can be changed to suit. You were correct in calling the value of the entry with self.input1.get().
Hope this has helped.
I am new in creating GUI. I am doing it in Python with Tkinter. In my program I calculate following characteristics
def my_myfunction():
my code ...
print("Centroid:", centroid_x, centroid_y)
print("Area:", area)
print("Angle:", angle)
I would like to ask for any help/tips how to display those values in GUI window or how to save them in .txt file so that I can call them in my GUI
Thanks in advance
Tkinter is easy and an easy way to do a GUI, but sometimes it can be frustrating. But you should have read the docs before.
However, you can do in this way.
from tkinter import *
yourData = "My text here"
root = Tk()
frame = Frame(root, width=100, height=100)
frame.pack()
lab = Label(frame,text=yourData)
lab.pack()
root.mainloop()
There are several ways to display the results of any operation in tkiner.
You can use Label, Entry, Text, or even pop up messages boxes. There are some other options but these will probably be what you are looking for.
Take a look at the below example.
I have a simple adding program that will take 2 numbers and add them together. It will display the results in each kind of field you can use as an output in tkinter.
import tkinter as tk
from tkinter import messagebox
class App(tk.Frame):
def __init__(self, master):
self.master = master
lbl1 = tk.Label(self.master, text = "Enter 2 numbers to be added \ntogether and click submit")
lbl1.grid(row = 0, column = 0, columnspan = 3)
self.entry1 = tk.Entry(self.master, width = 5)
self.entry1.grid(row = 1, column = 0)
self.lbl2 = tk.Label(self.master, text = "+")
self.lbl2.grid(row = 1, column = 1)
self.entry2 = tk.Entry(self.master, width = 5)
self.entry2.grid(row = 1, column = 2)
btn1 = tk.Button(self.master, text = "Submit", command = self.add_numbers)
btn1.grid(row = 2, column = 1)
self.lbl3 = tk.Label(self.master, text = "Sum = ")
self.lbl3.grid(row = 3, column = 1)
self.entry3 = tk.Entry(self.master, width = 10)
self.entry3.grid(row = 4, column = 1)
self.text1 = tk.Text(self.master, height = 1, width = 10)
self.text1.grid(row = 5, column = 1)
def add_numbers(self):
x = self.entry1.get()
y = self.entry2.get()
if x != "" and y != "":
sumxy = int(x) + int(y)
self.lbl3.config(text = "Sum = {}".format(sumxy))
self.entry3.delete(0, "end")
self.entry3.insert(0, sumxy)
self.text1.delete(1.0, "end")
self.text1.insert(1.0, sumxy)
messagebox.showinfo("Sum of {} and {}".format(x,y),
"Sum of {} and {} = {}".format(x, y, sumxy))
if __name__ == "__main__":
root = tk.Tk()
myapp = App(root)
root.mainloop()
I am trying to make an app with Python, Tkinter. In this programme in line 47, I have used a boolean statement. But it is giving me an error. I want to use boolean statement as a memory bit and want to use anywhere in programme.
import serial
import Tkinter
from Tkinter import *
class SerialViewer:
def __init__(self):
self.win = Tk()
self.ser = serial.Serial('com8',9600)
def bt1 (self):
self.ser.write('on')
def bt2 (self):
self.ser.write('off')
def bt3 (self):
self.ser.write(self.v.get())
def makewindow (self):
frame1 = Frame(self.win)
frame1.pack(side = LEFT)
b1 = Button(frame1, text = "ON", command = self.bt1)
b2 = Button(frame1, text = "OFF", command = self.bt2)
b1.grid(row = 0, column = 0)
b2.grid(row = 0, column = 1)
frame2 = Frame(self.win)
frame2.pack()
self.v = StringVar()
r1 = Radiobutton(frame2,text = 'on', variable = self.v, value = 'on')
r2 = Radiobutton(frame2,text = 'off', variable = self.v, value = 'off')
r1.select()
b3 = Button(frame2, text = 'send', command = self.bt3)
b3.pack(sid = RIGHT, padx = 5)
r1.pack(side = LEFT)
r2.pack(side = LEFT)
frame3 = Frame(self.win)
frame3.pack()
self.d = StringVar()
self.d.set('default')
label = Label(frame3, textvariable = self.d, relief = RAISED)
label.pack(side = RIGHT)
def update(self):
data = self.ser.readline(self.ser.inWaiting())
self.d.set(data)
if data == 'f1':
self.M1 = True
if self.M1:
print("ok tested")
self.win.after(100,self.update)
def run(self):
self.makewindow()
self.update()
self.win.mainloop()
SerialViewer().run()
The error is:Traceback (most recent call last): File "Untitled",
line 58
SerialViewer().run() File "Untitled", line 55, in run
self.update() File "Untitled", line 49, in update
if self.M1: AttributeError: SerialViewer instance has no attribute 'M1'
I think you should initialize M1 in the constructor. Like this:
def __init__(self):
self.win = Tk()
self.ser = serial.Serial('com8',9600)
self.M1 = False
Because when you get into update method and data != 'f1' it seeks the M1 propriety that doesn't exists.
In your update method, you only define self.M1 when your data is equal to "f1". When it isn't, self.M1 is not defined, so you receive this error.
To fix it, add an else clause to your if statement before, where self.M1 can be set to false.
I have a program running that is having issues when the timer runs. Every time "start" is hit, the application crashes. Any thoughts?
##-- Imports --##
import time
import openpyxl as xl
from Tkinter import *
##-- Classes --##
class App(Frame):
def startTimer(self):
self.check = True
self.now = time.strftime("%H:%M:%S")
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
def initUI(self):
self.parent.title("Emma's Time Manager")
self.pack(fill = BOTH, expand = 1)
def initWidget(self):
##Create button definitions##
self.buttonwidth = 12
self.quit = Button(self, text = "Quit", comman = self.quit, width = self.buttonwidth)
self.newClient = Button(self, text = "Add Client", command = lambda:self.newClientFunc(), width = self.buttonwidth)
self.timeStart = Button(self, text = "Start", command = lambda:self.startTimer(), width = self.buttonwidth)
self.timeEnd = Button(self, text = "End", command = lambda:self.endTimer(), width = self.buttonwidth)
self.saveBut = Button(self, text = "Save", command = lambda:self.saveFunc(), width = self.buttonwidth)
self.viewClient = Button(self, text = "View Client", command = lambda:self.viewCliFunc(), width = self.buttonwidth)
##Create lable definitions##
self.timer = Label(self, text = "00:00:00") ##self.timer used as display for timer##
##Create the listbox for Client Selection##
self.wb = xl.load_workbook("clients.xlsx")
self.clientNames = self.wb.get_sheet_names()
self.clivar = StringVar(self)
self.clivar.set(self.clientNames[0])
self.clilist = apply(OptionMenu, (self, self.clivar) + tuple(self.clientNames))
##Create Entry Box to describe work information##
self.info = Entry(self, width = 50)
##Create GUI for widgets##
self.clilist.grid(row = 0, column = 0)
self.timer.grid(row = 0, column = 1)
self.timeStart.grid(row = 0, column = 2)
self.timeEnd.grid(row = 0, column = 3)
self.info.grid(row = 1, column = 0, columnspan = 4)
self.newClient.grid(row = 2, column = 0)
self.viewClient.grid(row = 2, column = 1)
self.saveBut.grid(row = 2, column = 2)
self.quit.grid(row = 2, column = 3)
def __init__(self, parent):
Frame.__init__(self, parent, background = "light blue")
self.parent = parent
self.initUI()
self.initWidget()
def main():
try:
xl.load_workbook("clients.xlsx")
except:
temp = xl.Workbook()
temp.save("clients.xlsx")
temp.remove_sheet(temp.get_sheet_by_name("Sheet"))
root = Tk()
bob = App(root)
root.mainloop()
main()
Please note that most of the program is not yet finished. I just cannot seem to get this timer to run properly.
Looks like you have no way out of your while loop. You'll either need to set self.check to False, or break out of the loop.
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)