Python 2.7: Tkinter: Classes - Attribute Error [duplicate] - python-2.7

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 7 years ago.
Hello I am making a GUI for a program with Tkinter, but I keep getting an error:
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Users\jorge\Desktop\new 1.py", line 53, in browse_button
self.browse_entry.delete(0,END)
AttributeError: 'NoneType' object has no attribute 'delete'"
I am a noobie what it comes to classes so I don't know what I'm making wrong.
If you could help me I would appreciate it.
Thanks in advance!!
from Tkinter import *
from tkFileDialog import *
import ttk,os
class App(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.title("Subtitles Master")
self.iconbitmap(default = r"C:\Users\jorge\Desktop\Programas Python\notepad.ico")
mainframe = Frame(self)
mainframe.pack(side = "top")
mainframe.grid_rowconfigure(0, weight = 1)
mainframe.grid_columnconfigure(0, weight = 1)
self.frames = {}
for F in (StartPage, Timing):
frame = F(mainframe, self)
self.frames[F] = frame
frame.grid (row = 0, column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
filler1 = Frame(self, width = 30, height = 20).grid(column = 4, row = 0, rowspan = 2)
syncsubs_button = ttk.Button(self, text = "Sync Subtitles", state = DISABLED).grid(column = 5, row = 0)
timing_button = ttk.Button(self, text = "Edit Timing", command = lambda: controller.show_frame(Timing)).grid(column = 5, row = 1)
filler2 = Frame(self, width = 20, height = 20).grid(column = 6, row = 0, rowspan = 2)
syncsubs_label= Label(self, font = ("Alien Encounters", 20), text = "Sync Subtitles", fg = "dark green").grid(row = 2, columnspan = 6)
browse_label = Label(self, font = ("Calibri",12), text = "Subtitles to sync:").grid(row = 3, column = 0, sticky = "w")
filename1 = StringVar()
self.browse_entry = Entry(self, textvariable = filename1, width = 50).grid(row = 4, column = 1, columnspan = 5)
browse_button = ttk.Button(self, text = "Browse", command = self.browse_button).grid(row = 4, column = 0)
def browse_button(self):
filename = askopenfilename(title = "Choose a file",filetypes = (("Subtitles", "*.srt"), ("Text", "*.txt")))
self.browse_entry.delete(0,END)
self.browse_entry.insert(0,filename)
return filename
class Timing(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
filler1 = Frame(self, width = 30, height = 20).grid(column = 4, row = 0, rowspan = 2)
syncsubs_button = ttk.Button(self, text = "Sync Subtitles", command = lambda: controller.show_frame(StartPage)).grid(column = 5, row = 0)
timing_button = ttk.Button(self, text = "Edit Timing", state = DISABLED).grid(column = 5, row = 1)
filler2 = Frame(self, width = 20, height = 20).grid(column = 6, row = 0, rowspan = 2)
syncsubs_label= Label(self, font = ("Alien Encounters", 20), text = "Edit Timing", fg = "dark red").grid(row = 2, columnspan = 6)
window = App()
window.mainloop()

The problem is this line:
# returns None (Entry.grid(...))
self.browse_entry = Entry(self, textvariable = filename1, width = 50).grid(row = 4, column = 1, columnspan = 5)
Change to two lines:
# returns entry
self.browse_entry = Entry(self, textvariable = filename1, width = 50)
# do stuff with entry
self.browse_entry.grid(row = 4, column = 1, columnspan = 5)

Related

My entry widget replaces the item in the list instead of adding as a new item?

Instead of appending the job_list entry to the list, it replaces the item before when you try to input a new value. I think you can mainly focus on the store_job method, the job number entry and the enter job button. I'm not sure if I need a reset method or something so that the Entry widgets can take more data. Any help would be much appreciated.
from tkinter import *
class EntryGUI:
def __init__(self, parent):
self.cb = IntVar()
self.job_number_label= Label(parent, text = "Job number:")
self.job_number_label.grid(row = 1, column = 0)
self.job_number = Entry(parent)
self.job_number.focus()
self.job_number.grid(row=1, column = 1)
self.customer_name_label = Label(parent, text = "Customer name:")
self.customer_name_label.grid(row = 2, column = 0)
self.customer_name = Entry(parent)
self.customer_name.grid(row=2, column = 1)
self.distance_label= Label(parent, text = "Distance Travelled (km):")
self.distance_label.grid(row = 3, column = 0)
self.distance = Entry(parent)
self.distance.grid(row=3, column = 1)
self.min_spent_label= Label(parent, text = "Minutes spent on Virus protection:")
self.min_spent_label.grid(row = 4, column = 0)
self.min_spent = Entry(parent)
self.min_spent.grid(row=4, column = 1)
wof_tune= Checkbutton(parent, variable = self.cb, text = "check if WOF and tune is required",
onvalue = 100, offvalue = 0)
wof_tune.grid(row = 5, column = 0)
self.enter = Button(parent, text = "Enter Job", command = lambda:[self.store_job(),self.calculate()])
self.enter.grid(row = 6, column = 0)
self.show_all = Button(parent, text = "Show All")
self.show_all.grid(row = 6, column = 1)
def store_job(self):
self.job_list = []
self.customer_list = []
self.job_list.append(self.job_number.get())
self.customer_list.append(self.customer_name.get())
for i in self.job_list:
print (i)
def calculate(self):
self.cost_list = []
self.distance_calc = int(self.distance.get())
self.min_calc = int(self.min_spent.get())
self.cost = 0
#calculates the travel cost
#if the distance is less than 5km it costs 10
if self.distance_calc <= 5:
self.cost = 10
else:
self.distance_calc = self.distance_calc - 5 #-5 as you calclate the extra distance
self.distance_calc = self.distance_calc / 2 #divide by two as you add 50c per km
self.cost = self.distance_calc + 10 #initial 10 plus half the extra distance
#print(self.cost)
self.cost = self.cost + (self.min_calc * 0.8)
self.cost = self.cost + int(self.cb.get())
self.cost_list.append(self.cost)
print(self.cost_list)
self.enter_next()
def enter_next(self):
self.job_number.delete(0,END)
self.customer_name.delete(0, END)
self.distance.delete(0, END)
self.min_spent.delete(0, END)
self.enter.configure(state = NORMAL)
if __name__=="__main__":
root = Tk()
show_label = EntryGUI(root)
root.mainloop()
You were resetting the lists used to store the data entered every time the data is entered; you need to declare storage attributes in __init__, then use them to accumulate the data:
class EntryGUI:
def __init__(self, parent):
self.cb = IntVar()
self.job_number_label = Label(parent, text="Job number:")
self.job_number_label.grid(row=1, column=0)
self.job_number = Entry(parent)
self.job_number.focus()
self.job_number.grid(row=1, column=1)
self.customer_name_label = Label(parent, text="Customer name:")
self.customer_name_label.grid(row=2, column=0)
self.customer_name = Entry(parent)
self.customer_name.grid(row=2, column=1)
self.distance_label = Label(parent, text="Distance Travelled (km):")
self.distance_label.grid(row=3, column=0)
self.distance = Entry(parent)
self.distance.grid(row=3, column=1)
self.min_spent_label = Label(parent, text="Minutes spent on Virus protection:")
self.min_spent_label.grid(row=4, column=0)
self.min_spent = Entry(parent)
self.min_spent.grid(row=4, column=1)
wof_tune= Checkbutton(parent, variable=self.cb, text="check if WOF and tune is required",
onvalue =100, offvalue=0)
wof_tune.grid(row=5, column=0)
self.enter = Button(parent, text="Enter Job", command=self.acquire_entries)
self.enter.grid(row=6, column=0)
self.show_all = Button(parent, text="Show All")
self.show_all.grid(row=6, column=1)
self.job_list = []
self.customer_list = []
self.cost_list = []
def acquire_entries(self):
self.store_job()
self.calculate()
def store_job(self):
self.job_list.append(self.job_number.get())
self.customer_list.append(self.customer_name.get())
def calculate(self):
self.distance_calc = int(self.distance.get())
self.min_calc = int(self.min_spent.get())
self.cost = 0
# ... unchanged below

How to divide container into different sets of columns in tkinter GUI?

I am trying to make a GUI in tkinter. So far I have reached this level.
The problem is, I am not able to centre the 4 buttons at the bottom, one of them is going out of the assigned width. This is because while making a top frame, I have assigned columnspan to be 3. If I make it 4 then the centring of the middle part goes off.
import Tkinter as tk
root = tk.Tk()
root.title('Steady State Data Processing')
root.geometry('{}x{}'.format(900, 500))
topFrame = tk.Frame(root, bg = 'lavender', width = 900, height=100, relief = 'raised') # , padx = 100, pady=100
topFrame.grid(row = 0, column = 0, columnspan = 3, sticky="w")
labelCps = tk.Label(root, text='Cps', width = 0, height = 0, padx = 10, pady = 10)
labelIgn = tk.Label(root, text='Ign', width = 0, height = 0, padx = 10, pady = 10)
labelInj = tk.Label(root, text='Inj', width = 0, height = 0, padx = 10, pady = 10)
labelCps.grid(row = 1, column = 0, sticky='we')
labelIgn.grid(row = 1, column = 1, sticky='we')
labelInj.grid(row = 1, column = 2, sticky='we')
cpsFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
cpsFrame.grid(row = 2, column = 0, sticky="nsew")
ignFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
ignFrame.grid(row = 2, column = 1, sticky="nsew")
injFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
injFrame.grid(row = 2, column = 2, sticky="nsew")
labelAdv = tk.Label(cpsFrame, anchor = 'center', text='Cps adv threshold:')
labelAdv.grid(row = 0, column = 0, sticky = 'w')
entryAdv = tk.Entry(cpsFrame)
entryAdv.grid(row = 0, column = 1, sticky = 'e')
labelIgn = tk.Label(ignFrame, justify = 'left', text = 'Dwell start threshold:')
labelIgn.grid(row = 0, column = 0, sticky = 'w')
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 0, column = 1)
labelIgn = tk.Label(ignFrame, anchor = 'center', text = 'Dwell end threshold:')
labelIgn.grid(row = 1, column = 0)
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 1, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj start threshold:')
labelInj.grid(row = 0, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 0, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj end threshold:')
labelInj.grid(row = 1, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 1, column = 1)
root.grid_rowconfigure(3, pad = 50)
applyButton = tk.Button(root, text = 'Apply', padx = 30, pady = 15)
applyButton.grid(row = 3, columnspan = 3)
text = ['Plot raw data', 'Plot tooth rpm', 'Plot cycle rpm', 'Plot ign data']
count = 0
for t in text:
dataButton = tk.Button(root ,text = t, width = 5, height = 5 ,anchor = 'center', padx = 30, pady = 15)
dataButton.grid(row = 4, column = count, sticky = 'news')
# dataButton.grid_columnconfigure(count, weight = 2)
count = count + 1
root.mainloop()
To center the buttons, they need to be in a frame. Second, to make them fill the space allocated to them by grid, you have to configure the grid columns in the frame to expand. I'm not sure whether you wanted padding between the buttons, but I added some to the grid command.
import Tkinter as tk
root = tk.Tk()
root.title('Steady State Data Processing')
root.geometry('{}x{}'.format(900, 500))
topFrame = tk.Frame(root, bg = 'lavender', width = 900, height=100, relief = 'raised') # , padx = 100, pady=100
topFrame.grid(row = 0, column = 0, columnspan = 3, sticky="w")
labelCps = tk.Label(root, text='Cps', width = 0, height = 0, padx = 10, pady = 10)
labelIgn = tk.Label(root, text='Ign', width = 0, height = 0, padx = 10, pady = 10)
labelInj = tk.Label(root, text='Inj', width = 0, height = 0, padx = 10, pady = 10)
labelCps.grid(row = 1, column = 0, sticky='we')
labelIgn.grid(row = 1, column = 1, sticky='we')
labelInj.grid(row = 1, column = 2, sticky='we')
cpsFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
cpsFrame.grid(row = 2, column = 0, sticky="nsew")
ignFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
ignFrame.grid(row = 2, column = 1, sticky="nsew")
injFrame = tk.Frame(root, width = 300, height = 100, relief = 'raised') # , padx = 100, pady=100
injFrame.grid(row = 2, column = 2, sticky="nsew")
labelAdv = tk.Label(cpsFrame, anchor = 'center', text='Cps adv threshold:')
labelAdv.grid(row = 0, column = 0, sticky = 'w')
entryAdv = tk.Entry(cpsFrame)
entryAdv.grid(row = 0, column = 1, sticky = 'e')
labelIgn = tk.Label(ignFrame, justify = 'left', text = 'Dwell start threshold:')
labelIgn.grid(row = 0, column = 0, sticky = 'w')
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 0, column = 1)
labelIgn = tk.Label(ignFrame, anchor = 'center', text = 'Dwell end threshold:')
labelIgn.grid(row = 1, column = 0)
entryIgn = tk.Entry(ignFrame)
entryIgn.grid(row = 1, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj start threshold:')
labelInj.grid(row = 0, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 0, column = 1)
labelInj = tk.Label(injFrame, anchor = 'center', text = 'Inj end threshold:')
labelInj.grid(row = 1, column = 0)
entryInj = tk.Entry(injFrame)
entryInj.grid(row = 1, column = 1)
root.grid_rowconfigure(3, pad = 50)
applyButton = tk.Button(root, text = 'Apply', padx = 30, pady = 15)
applyButton.grid(row = 3, columnspan = 3)
text = ['Plot raw data', 'Plot tooth rpm', 'Plot cycle rpm', 'Plot ign data']
count = 0
# Button frame
frame = tk.Frame(root)
frame.grid(row=4, column=0, sticky='news', columnspan=4)
for t in text:
# Expand the column widths as required by the window cavity.
frame.grid_columnconfigure(count, weight=1)
dataButton = tk.Button(frame ,text = t, width = 5, height = 5 ,anchor = 'center', padx = 30, pady = 15)
dataButton.grid(row = 0, column = count, sticky = 'news', padx=30)
# dataButton.grid_columnconfigure(count, weight = 2)
count = count + 1
root.mainloop()

Object Oriented Tkinter Coding: Changing text and Updating

So I have been teaching myself Object Oriented Programming for Tkinter projects as I clearly see that they are much more organized for large amounts of coding. However I must admit that I've been coasting by simply copying various bits of coding from online, not fully understanding what its purpose is.
This has lead me to the point that my code does not work at all and I have no idea why not. The first issue is an issue with simply changing an aspect of other widgets.
I have this sample code:
import Tkinter as tk
LARGE_FONT = ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0 , weight = 1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
button = tk.Button(self, text = "Change Label", command = self.change)
button.pack(pady = 10, padx = 10)
def change(self):
label["text"] = "It has changed"
app = SeaofBTCapp()
app.mainloop()
Which SHOULD be a simple enough code that, with a button press, change the label from "Start Page" to "It has changed". But whenever I run it, it says that the global variable "label" is not defined. Additionally, if I then change it to self.label, it states that StartPage instance has no attribute 'label'. I don't know what I'm doing wrong.
Additionally, in a similar vein, I'm working on a project that has a SideBar class and a Main class tied to one MainApplication class. The Main class takes a value and displays it on a Frame in the Main class. Following this, a button in the SideBar increases that value by 1. But the Main display doesn't update and I have no idea how to tie the Main updating with the button in the SideBar.
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root):
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.sidebar = SideBar(self.parent)
self.main = Main(self.parent)
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()
All help would be appreciated, but please try and not use a lot of technical terms, as I am still learning.
In the first scenario replace:
label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
With:
self.label = tk.Label(self, text = "Start Page", font = LARGE_FONT)
self.label.pack(pady = 10, padx = 10)
And also in the function change put it like this:
self.label["text"] = "It has changed"
And in your second problem i changed the code a little bit so it works:
import Tkinter as tk
something = [0, 6]
class Main():
def __init__(self, root):
mainboard = tk.Frame(root, height = 100, width = 100)
self.maincanvas = tk.Canvas(mainboard, bd = 1, bg = "white")
mainboard.grid(row = 0, column = 0)
self.maincanvas.grid(row = 0, column = 0)
self.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1]))
class SideBar():
def __init__(self, root, main):
self.main = main # Putting the main object to self.main
sidebarframe = tk.Frame(root, height = 100, width = 100)
button = tk.Button(sidebarframe, width = 20, text = "Change Value", command = self.add)
sidebarframe.grid(row = 0, column = 1)
button.grid(row = 0, column = 0)
def add(self):
something[1] += 1
self.main.maincanvas.delete("all") # Removing everything from canvas
self.main.maincanvas.create_text(45, 50, anchor = "center", text = str(something[1])) # Inserting the new value
print something[1]
class MainApplication():
def __init__(self, parent):
self.parent = parent
self.main = Main(self.parent) # The main needs to run first
self.sidebar = SideBar(self.parent, self.main) # So that SideBar can use its canvas
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root)
root.mainloop()

Python-2.7.10 Password GUI not working

Working on a Python 2.7.10 program, for a password gui but it is giving the error that Application is not defined. I am not sure if there is something wrong with Class Application(Frame) or app = Application(root), because it ask for me to define Application but I don't why they would ask me.
from Tkinter import *
class Application(Frame):
def _init_(self, master):
Frame._init_(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.instruction = Label(self, text = "Enter the password")
self.instruction.grid(row = 0, column = 0, columnspan = 2, sticky = W)
self.password = Entry(self)
self.password.grid(row = 1, column = 1, sticky = W)
self.submit_button = Button(self, text = "Submit", commmand = self.reveal)
self.submit_button.grid(row = 2, column = 0, sticky = W)
self.text = Text(self, width = 35, height = 5, wrap = WORD)
self.text.grid(row = 3, column = 0, columnspan = 2, sticky = W)
def reveal(self):
content = self.password.get()
if content == "password":
message = "You have the order"
else:
message = "Access denied."
self.text.delete(0.0, END)
self.text.insert(0.0, message)
root = Tk()
root.title("Password")
root.geometry("250x150")
app= Application(root)
root.mainloop()
I've fixed your code, here it is:
from Tkinter import *
class Application(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.instruction = Label(self, text = "Enter the password")
self.instruction.grid(row = 0, column = 0, columnspan = 2, sticky = W)
self.password = Entry(self)
self.password.grid(row = 1, column = 1, sticky = W)
self.submit_button = Button(self, text = "Submit", command = self.reveal)
self.submit_button.grid(row = 2, column = 0, sticky = W)
self.text = Text(self, width = 35, height = 5, wrap = WORD)
self.text.grid(row = 3, column = 0, columnspan = 2, sticky = W)
def reveal(self):
content = self.password.get()
if content == "password":
message = "You have the order"
else:
message = "Access denied."
self.text.delete(0.0, END)
self.text.insert(0.0, message)
root = Tk()
root.title("Password")
root.geometry("250x150")
app= Application(root)
root.mainloop()
Your problems were:
You used _init_ instead of __init__
Typo of "commmand" instead of "command"
Last two lines of procedure reveal in Application were incorrectly indented (logic error, not syntax or run-time)
It wasn't really clear what your question was to be honest and I just did this in Python 3.4.3 and made changes so that it should run in Python 2.7.10. I hope that helps.

Getting Attribute error in Python

Here is my code along with the error message.
from Tkinter import *
class Window01 (Frame):
def __init__(self, master):
Frame.__init__(self)
self.reveal()
self.create_widget()
self.grid()
def create_widget(self):
self.lbl = Label (self, text = "This is a Widget App.")
self.lbl.grid(row =1, column =0, columnspan =2, sticky = W)
self.entbx = Entry(self)
self.entbx.grid(row = 1, column = 1, sticky = W)
self.bttn = Button (self, text = "Widget Button", command = self.reveal)
self.bttn.grid(row = 2, column = 0, sticky = W)
self.txt = Text (self, width =35, height = 5, wrap = WORD)
self.txt.grid(row = 3, column = 0, columnspan =2, sticky = W)
def reveal (self):
contents = self.entbx.get()
if contents =="magic":
message = "Access Granted"
else:
message = "Denied"
self.txt.delete(0.0, END)
elf.txt.insert(0.0, message)
root = Tk()
root.title ("Widget_Button")
root.geometry ("300x150")
app = Window01 (root)
root.mainloop()
File "C:\PyDev\Py_Widgets101\src\Py_Widget03.py", line 10, in init
self.reveal()
File "C:\PyDev\Py_Widgets101\src\Py_Widget03.py", line 30, in reveal
contents = self.entbx.get()
AttributeError: Window01 instance has no attribute 'entbx'
self.entbx is created by create_widget(). You are calling reveal() -- which requires self.entbx -- before you've called create_widget():
self.reveal()
self.create_widget()