I'm trying to add items to the listbox, but every time I try it, it's saying that the global name "title_input" is not defined. I don't understand why this doesn't work, because the last one that I did with this exact same structure didn't give me that error. I'm new to this, and the other tutorials and questions I read about global name errors didn't make sense to me. Thanks for the help!
from Tkinter import *
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
self.list = Listbox(self, selectmode=BROWSE)
self.list.grid(row = 1, column = 4, rowspan = 10, columnspan = 3, sticky = W, padx = 5, pady = 5)
def create_widgets(self):
#setlist box - may not stay text box?
self.setlist = Text(self, height = 14, width = 25)
self.setlist.grid(row = 1, column = 0, rowspan = 10, columnspan = 3, sticky = W, padx = 5, pady = 5)
self.setlistLabel = Label(self, text = "SetList")
self.setlistLabel.grid(row = 0, column = 1, sticky = W, padx = 5, pady = 5)
#Library label
self.libraryLabel = Label(self, text = "Library")
self.libraryLabel.grid(row = 0, column = 5, sticky = W, padx = 5, pady y = 5)
#Library button/input
self.add_title = Button(self, text = "Add Title", command = self.add_item)
self.add_title.grid(row = 16, column = 5, sticky = W, padx = 5, pady = 5)
self.title_input = Entry(self)
self.title_input.grid(row = 16, column = 4, sticky = W, padx = 5, pady = 5)
def add_item(self):
list.insert(END, title_input.get())
def get_list(event):
index = list.curselection()[0]
seltext = list.get(index)
setlist.insert(0, seltext)
root = Tk()
root.title("SetList Creator")
root.geometry("500x500")
app = Application (root)
root.mainloop()
title_input is defined in your instance namespace but it is not defined in your global namespace. When you reference an unqualified title_input in your class method add_item, Python looks for title_input in the global namespace. When it doesn't find it there it gives you that error. Adding the self qualifier, self.title_input, to indicate that you wish to reference title_input in the instance namespace, will resolve the error.
Related
Hey I would like to create a frame which contains a Listbox and some buttons. What I would like to do is to somehow pass as an argument a name of this listbox. This is my current code in which I set the name of this listbox to master.thisListbox but I would like to pass it somehow as argument. Is it possible or should I separately crate a listbox in my App and the pass it as an argument to a frame? I'm going to create a lot of such listboxes in my App hence the name of listbox shouldn't be the same. I'm pretty new in OOP.
class myApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.dateFrame = DateFrame(self)
self.dateFrame.grid(row = 0, column = 0)
print(self.day.get())
self.myFrame = ListboxFrame(self, "Label!", [1,2,3])
self.myFrame.grid(row = 1, column = 0)
x = self.thisListbox.get(0, END)
print(x)
class DateFrame(ttk.Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master)
# Day
ttk.Label(self, text = "Day", width = 4).grid(row = 0, column = 0, padx = 3, pady = 3)
master.day = IntVar(master, value = 31)
self.dayCB = ttk.Combobox(self, values = [x for x in range(1, 32)], textvariable = master.day, width = 4)
self.dayCB.grid(row = 1, column = 0, padx = 3, pady = 3)
# Month
ttk.Label(self, text = "Month", width = 6).grid(row = 0, column = 1, padx = 3, pady = 3)
self.month = IntVar(master, value = 12)
self.monthCB = ttk.Combobox(self, values = [x for x in range(1, 13)], textvariable = self.month, width = 4)
self.monthCB.grid(row = 1, column = 1, padx = 3, pady = 3)
# Year
ttk.Label(self, text = "Year", width = 4).grid(row = 0, column = 2, padx = 3, pady = 3)
self.year = IntVar(master, value = 2021)
self.yearCB = ttk.Spinbox(self, from_ = 2020, to = 2100, textvariable = self.year, width = 6)
self.yearCB.grid(row = 1, column = 2, padx = 3, pady = 3)
class ListboxFrame(ttk.Frame):
def __init__(self, master, labelText, values, selectmode = "extended", height = 6, width = 30):
ttk.Frame.__init__(self, master)
# Listbox
ttk.Label(self, text = labelText).grid(row = 0, column = 0, columnspan = 3)
master.thisListbox = tk.Listbox(self, selectmode = selectmode, height = height, width = width)
master.thisListbox.grid(row = 1, column = 0, columnspan = 3, padx = 2, pady = 2)
# Entry
self.entry = ttk.Entry(self)
self.entry.grid(row = 2, column = 0, padx = 2, pady = 2)
# Buttons
self.addButton = ttk.Button(self, text = "Add", width = 4, command = self.Add)
self.addButton.grid(row = 2, column = 1, padx = 2, pady = 2)
self.deleteButton = ttk.Button(self, text = "Delete", width = 6, command = self.Delete)
self.deleteButton.grid(row = 2, column = 2, padx = 2, pady = 2)
for v in values:
master.thisListbox.insert(END, v)
def Add(self):
if self.entry.get() == "": return
master.thisListbox.insert(END, self.entry.get())
self.entry.delete(0, END)
def Delete(self):
for index in reversed(master.thisListbox.curselection()):
master.thisListbox.delete(index)
# listbox.config(height = listbox.size())
I am trying to make a Tkinter GUI that takes Excel documents, reads them, and exports them to the window. The issue is when I changed the code to below to incorporate class structure, I cannot make the GUI load properly anymore.
import tkinter as tk
from tkinter.filedialog import askopenfilename
def NewFile():
print("New File!")
def OpenFile():
name = askopenfilename()
print(name)
def About():
print("About works")
def deletelist():
listbox.delete(0, END)
class MainApplication(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.frame = tk.Frame(self.master)
self.load = tk.Button(self.frame, text = "Load XLSX File", command = OpenFile)
self.load.grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'w')
self.ckframe = tk.LabelFrame(self.frame, text="Currency Selections")
self.ckframe.grid(row = 1, column = 0, padx = 5, pady = 5, stick = 'nesw')
self.prochk = tk.Checkbutton(self.ckframe, text = '1 Currency').grid(row = 1, column = 0, columnspan = 2, sticky = 'w')
self.msnchk = tk.Checkbutton(self.ckframe, text = '2 Currency').grid(row = 1, column = 2, columnspan = 2, sticky = 'w')
self.nightschk = tk.Checkbutton(self.ckframe, text = '3 Currency').grid(row = 1, column = 4, columnspan = 2, sticky = 'w')
self.semichk = tk.Checkbutton(self.ckframe, text = '4 Currency').grid(row = 2, column = 0, columnspan = 2, sticky = 'w')
self.instqualCRchk = tk.Checkbutton(self.ckframe, text = '5 Currency').grid(row = 2, column = 2, columnspan = 2, sticky = 'w')
self.msnCRchk = tk.Checkbutton(self.ckframe, text = '6 Currency').grid(row = 2, column = 4, columnspan = 2, sticky = 'w')
self.listbox = tk.Listbox(self.frame, width = 83)
self.listbox.grid(row = 3, column = 0, columnspan = 1, sticky = 'w') # Fix width size function
self.listbox.insert(1, 'Test1')
self.listbox.insert(0, 'Test2')
self.save = tk.Button(self.frame, text = "Save").grid(row = 8, column = 0, padx = 5, pady = 5, stick = 'e')
self.delete = tk.Button(self.frame, text = "Delete", command = deletelist).grid(row = 8, column = 0, padx = 45, pady = 5, stick = 'e')
if __name__ == '__main__':
root = tk.Tk()
MainApplication(root)
root.mainloop()
I searched a lot trying to find a solution to using classes with tkinter GUI and the grid system but I mostly found ways to make GUIs with pack() solution.
The instance of MainApplication is a frame. You never call pack or place or grid on that instance so that frame and all of its children will be invisible.
This frame creates another frame that contains all of the other widgets, self.frame. You never call pack, place, or grid on it either, so it and all of its children will be invisible.
Since the widgets are in a frame that is invisible, and that frame itself is invisible, none of the other widgets will be visible.
The first thing to do is to get rid of self.frame. Remove the line that creates it, and everywhere you reference self.frame, replace it with self. Since self in this context is already a frame it makes no sense to create another frame inside.
Next, you need to add the instance of MainApplication to the window. Since it's the only widget directly in the root window, pack is the simplest choice.
root = tk.Tk()
app = = MainApplication(root)
app.pack(fill="both", expand=True)
Trying to split my parent window in several functional parts, one of which will be dealing with weather
data and etc and another one will be located in the right side and contain the map image, preferably extending at full height. The image doesn't want to come up though.. Please help
import pyowm
from tkinter import *
import tkinter.messagebox
from PIL import Image, ImageTk
owm = pyowm.OWM('....') # You MUST provide a valid API key
class MyWindow(tkinter.Frame):
def __init__(self, win):
super(MyWindow, self).__init__()
self.lbl=Label(win, text="Weather info", fg='black', font=("Helvetica", 11))
self.lbl1=Label(win, text='Wind speed')
self.lbl2=Label(win, text='Wind direction')
self.lbl.grid(row = 0, column = 0, sticky = W, pady = 2)
self.lbl1.grid(row = 1, column = 0, sticky = W, pady = 2)
self.lbl2.grid(row = 2, column = 0, sticky = W, pady = 2)
# widgets for destination and weather output
self.e1=Entry()
self.e2=Entry()
self.e3=Entry(bd=3)
# this will arrange entry widgets
self.e1.grid(row = 0, column = 1, pady = 2)
self.e2.grid(row = 1, column = 1, pady = 2)
self.e3.grid(row = 2, column = 1, pady = 2)
self.btn1 = Button(win, text='Get weather', command=self.getWeather)
self.btn1.grid(row = 3, column = 1, pady = 2)
self.btn1.bind('<Button-1>', self.getWeather)
img = Image.open(r"/User/.../pic.png")
photo = ImageTk.PhotoImage(img)
# setting image with the help of label
self.imgLBL = Label(self, image = photo)
self.imgLBL.grid(row = 0, column = 2, columnspan = 2, rowspan = 2, padx = 5, pady = 5)
self.imgLBL.image = photo
#### Get weather function, etc...###
window=Tk()
mywin=MyWindow(window)
window.title('name')
window.geometry("2732x2048")
window.configure(bg='grey')
window.mainloop()
Replace last few lines with this:
self.photo = ImageTk.PhotoImage(Image.open(r"/User/.../pic.png"))
# setting image with the help of label
self.imgLBL = Label(window, image=self.photo)
self.imgLBL.grid(row = 0, column = 2, columnspan = 2, rowspan = 2, padx = 5, pady = 5)
self.imgLBL.image = self.photo
i'm kinda new tkinter and i ran into a problem while using tkinter with python. I'm trying to get all of the buttons i have right now to take a number and add to it if the button is clicked or not, i ran into a wall and i have no idea how to fix it. Here's my code for reference.
from tkinter import *
class Application(Frame):
def __init__(self, master):
super(Application, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self):
Label(self,
text = "Enter information for services you need on your car"
).grid(row = 0, column = 0, columnspan = 2, sticky = W)
#Oil Change
Label(self,
text = "Oil Change"
).grid(row = 2, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$26.00",
#error here
variable = self.oil
).grid(row = 2, column = 1, sticky = W)
#Lube Job
Label(self,
text = "Lube Job"
).grid(row = 3, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$18.00",
variable = self.is_itchy
).grid(row = 3, column = 1, sticky = W)
#Radiator Flush
Label(self,
text = "Radiator Flush"
).grid(row = 4, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$30.00",
variable = self.is_itchy
).grid(row = 4, column = 1, sticky = W)
#Transmission Flush
Label(self,
text = "Oil Change"
).grid(row = 5, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$80.00",
variable = self.is_itchy
).grid(row = 5, column = 1, sticky = W)
#Inspection
Label(self,
text = "Inspection"
).grid(row = 6, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$15.00",
variable = self.is_itchy
).grid(row = 6, column = 1, sticky = W)
#Muffler Replacement
Label(self,
text = "Muffler Replacement"
).grid(row = 7, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$100.00",
variable = self.is_itchy
).grid(row = 7, column = 1, sticky = W)
#Tire Rotation
Label(self,
text = "Tire Rotation"
).grid(row = 8, column = 0, sticky = W)
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "$20.00",
variable = self.is_itchy
).grid(row = 8, column = 1, sticky = W)
#Buttons
Button(self,
text = "Click for total price",
command = self.tell_story
).grid(row = 9, column = 0, sticky = W)
self.story_txt = Text(self, width = 35, height = 5, wrap = WORD)
self.story_txt.grid(row = 10, column = 0, columnspan = 3)
Button(self,
text = "Quit",
command = quit
).grid(row = 9, column = 1, sticky = W)
def tell_story(self):
""" Fill text box with new story based on user input. """
# get values from the GUI
if self.oil.get():
print("Goofus")
# create the story
story = Price
# display the story
self.story_txt.delete(0.0, END)
self.story_txt.insert(0.0, story)
root = Tk()
root.title("Joe's repair shop")
app = Application(root)
root.mainloop()
Here is the error i am getting
Traceback (most recent call last):
File "C:\Users\Kevin Holstein\Desktop\Classes\Python\Labs\Lab 10\Repair shop
kholstein.py", line 127, in <module>
app = Application(root)
File "C:\Users\Kevin Holstein\Desktop\Classes\Python\Labs\Lab 10\Repair shop
kholstein.py", line 8, in __init__
self.create_widgets()
File "C:\Users\Kevin Holstein\Desktop\Classes\Python\Labs\Lab 10\Repair shop
kholstein.py", line 24, in create_widgets
variable = self.oil
AttributeError: 'Application' object has no attribute 'oil'
On this line:
Checkbutton(self, text = "$26.00", variable = self.oil).grid(row = 2, column = 1, sticky = W)
You declare that the variable attribute of the Checkbutton widget should be equal to self.oil which you never give a value to, this throws an error as tkinter is trying to assign something which doesn't exist to this attribute.
Hi there in my code I'm am getting an the error AttributeError: 'GUI' object has no attribute 'calculate_button' And I don't know why its not working when I am using two classes. Also I don't want to make the class inherit each other nor make it an object.
Here is my code:
from tkinter import *
from tkinter import ttk
class Logic:
def __init__(self,a,b,c,d):
self.a = a
self.b = b
self.c = c
self.d = d
as_meter = dict(mm=0.001, cm=0.01, inch=0.0254,ft=0.3048, yd=0.9144, m=1.0,km=1000.0, mi=1609.344,)
def calculate(self, *args):
try:
v = float(c)
except ValueError:
self.d.set('Invalid Input')
return
m = v * sign * self.as_meter [self.a]
r = m/self.as_meter[self.b]
answer = (self.d.set("{:.5g}".format(r)))
return answer
class GUI:
def __init__(self,root):
self.notebook = ttk.Notebook(root)
self.notebook.pack()
self.length_frame = ttk.Frame(self.notebook)
self.notebook.add(self.length_frame, text = 'Length')
#Combobox
self.measurements = StringVar()
self.Combobox_Length_Left = ttk.Combobox(self.length_frame, textvariable = self.measurements, values = ('mm', 'cm', 'inch', 'ft', 'yd', 'm', 'km', 'mi'), width = 10,state=['readonly'])
self.Combobox_Length_Left.current(5)
self.Combobox_Length_Left.grid(row = 2, column = 0, padx = 5, pady = 5, sticky = E)
self.measurements1 = StringVar()
self.Combobox_Length_Right = ttk.Combobox(self.length_frame, textvariable = self.measurements1, value = ('mm', 'cm', 'inch', 'ft', 'yd', 'm', 'km', 'mi'), width = 10,state = ['readonly'])
self.Combobox_Length_Right.current(5)
self.Combobox_Length_Right.grid(row = 2, column = 2, padx = 5, pady = 5, sticky = E)
#Labels
self.Conversion = ttk.Label(self.length_frame, text = 'Convertion:').grid(row = 1, column = 0, padx = 5, pady = 5, sticky = W)
self.Label_Blank = ttk.Label(self.length_frame, text = '').grid(row = 1, column = 1, padx = 5, pady = 5, sticky = E)
self.Label_To2 = ttk.Label(self.length_frame, text = 'to').grid(row = 2, column = 1, padx = 5, pady = 5, sticky = E)
self.Label_To = ttk.Label(self.length_frame, text = 'to').grid(row = 3, column = 1, padx = 5, pady = 5, sticky = E)
#Entry Boxes
self.Text_Length_Left = StringVar()
self.Entry_Length_Left = ttk.Entry(self.length_frame, textvariable = self.Text_Length_Left,width = 13)
self.Entry_Length_Left.grid(row = 3, column = 0, padx = 5, pady = 5)
self.Text_Length_Right = StringVar()
self.Entry_Length_Right = ttk.Entry(self.length_frame, textvariable = self.Text_Length_Right,width = 13, state='readonly')
self.Entry_Length_Right.grid(row = 3, column = 2, padx = 5, pady = 5)
def calculate_button(self):
c_l = self.measurements.get()
c_r = self.measurements1.get()
e_l = self.Text_Length_Left.get()
e_r = self.Text_Length_Right.get()
c = Logic(c_l,c_r,e_l,e_r)
self.Text_Length_Right.set('')
self.Text_Length_Right.set(c.calulate())
#Button
self.Convert_Button = ttk.Button(self.length_frame, text = 'Convert',command = calculate_button, width = 10).grid(row = 1, column = 2, sticky = S)
def main():
root = Tk()
app = GUI(root)
root.title('Metric Calculator')
root.resizable(False,False)
root.mainloop()
main()
Thanks for any help!
There are few issues with your code:
As #Tadhg McDonald-Jensen commented you, calculate_button() is wrongly intended and does not belong to GUI() class
As #MotKohn answered, you must remove () from calculate_button() in Convert_Button button.
Logic() is not defined neither in GUI() nor in Converversion() classes.
unindent calculate_button 1 level. It should not be a function in the init function rather a function of the class GUI. Remove () as mentioned in comment.
There is still a bug,
NameError: name 'Logic' is not defined