[Tkinter] Can't update label in new tk window, object has no attribute - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [Tkinter] Can't update label in new tk window, object has no attribute (/thread-38049.html) |
Can't update label in new tk window, object has no attribute - tompranks - Aug-27-2022 Hi, I have this code but i get the error "object has no attribute". from tkinter import * root = Tk() root.geometry("300x300") count = 20 pop_label = None def ACdriver(option): # pop.destroy() global count if option == "UP": count = count + 1 else: count = count - 1 my_label.config(text=count) pop_label.config(text=count) def ACwindowdriver(): global pop pop = Toplevel(root) pop.title("My Popup") pop.geometry("150x200+00+00") pop.overrideredirect(True) #Borderless pop.config(bg="black") pop_label = Label(pop, bg="green", fg="white", font=("helvetica", 12)) pop_label.config(text=count) pop_label.grid(row=1, column=0, pady=10) my_frame = Frame(pop, bg="black") my_frame.grid(row=1, column=1, pady=10) heatdriver = Button(my_frame, command=lambda: ACdriver("UP"), bg="black") heatdriver.grid(row=2, column=2, pady=10) colddriver = Button(my_frame, command=lambda: ACdriver("DOWN"), bg="black") colddriver.grid(row=3, column=2, pady=10) def destroy(): pop.destroy() destroy_button = Button(root, text="destroy", command=destroy) destroy_button.place(x=1, y=1) ACdriver_button = Button(root, text="ACwindowdriver", command=ACwindowdriver) ACdriver_button.pack(pady=50) my_label = Label(root, text="") my_label.pack(pady=20) root.mainloop()I am trying to update the number inside the new tk window called "pop" but the number only updates after i press "destroy" and "ACwindowdriver" again. When i press one button inside the window pop i get the error "'NoneType' object has no attribute 'config'". Thankfull for all help. Kind regards Tom RE: Can't update label in new tk window, object has no attribute - Yoriz - Aug-27-2022 The short answer is the pop_label only exists locally to ACwindowdriver using global in GUI code is not ideal, I prefer to code GUI using classes.Note: see Namespace flooding with * imports The code rewritten answer, using classes and an IntVar import tkinter as tk class AcWindowDriver(tk.Toplevel): def __init__(self, count, *args, **kwargs): super().__init__(*args, *kwargs) self.title("My Popup") self.geometry("150x200+00+00") self.overrideredirect(True) # Borderless self.config(bg="black") self.count = count pop_label = tk.Label( self, bg="green", fg="white", font=("helvetica", 12), textvariable=count ) pop_label.config(text=count) pop_label.grid(row=1, column=0, pady=10) my_frame = tk.Frame(self, bg="black") my_frame.grid(row=1, column=1, pady=10) heatdriver_btn = tk.Button( my_frame, command=self._on_heatdriver_btn, bg="black" ) heatdriver_btn.grid(row=2, column=2, pady=10) colddriver_btn = tk.Button( my_frame, command=self._on_colddriver_btn, bg="black" ) colddriver_btn.grid(row=3, column=2, pady=10) def _on_heatdriver_btn(self): current_count = self.count.get() self.count.set(current_count + 1) def _on_colddriver_btn(self): current_count = self.count.get() self.count.set(current_count - 1) class MainFrame(tk.Frame): def __init__(self, *args, **kwargs): super().__init__(*args, *kwargs) self.count = tk.IntVar(self, 20) self.ac_window_driver = None destroy_btn = tk.Button(self, text="destroy", command=self._on_destroy_btn) destroy_btn.place(x=1, y=1) ac_driver_btn = tk.Button( self, text="ACwindowdriver", command=self._on_ac_driver_btn ) ac_driver_btn.pack(pady=50) my_label = tk.Label(self, textvariable=self.count) my_label.pack(pady=20) def _on_destroy_btn(self): if not self.ac_window_driver: return self.ac_window_driver.destroy() self.ac_window_driver = None def _on_ac_driver_btn(self): if self.ac_window_driver: return self.ac_window_driver = AcWindowDriver(self.count, self) def main(): app = tk.Tk() app.geometry("300x300") main_frame = MainFrame(app) main_frame.pack() app.mainloop() if __name__ == "__main__": main() RE: Can't update label in new tk window, object has no attribute - deanhystad - Aug-27-2022 You could make pop_label a global def ACwindowdriver(): global pop, pop_labelbut it would be far better to make it an attribute of the class. Actually, I wouldn't expose the labels at al.I would instead create a tkinter.IntVariable, and use this to set the text of the labels. import tkinter as tk class PopupWindow(tk.Toplevel): def __init__(self, parent, count): super().__init__(parent, bg="black") self.overrideredirect(True) self.count = count tk.Label( self, textvariable=count, bg="green", fg="white", font=("helvetica", 12), width=3).pack(padx=5, pady=5) tk.Button( self, text=" Up ", command=lambda: self.increment(1), bg="black", fg="green").pack(padx=5, pady=5) tk.Button( self, text="Down", command=lambda: self.increment(-1), bg="black", fg="green").pack(padx=5, pady=5) def increment(self, amount): self.count.set(self.count.get() + amount) class RootWindow(tk.Tk): def __init__(self): super().__init__() self.title("Root Window") self.popups = [] self.count = tk.IntVar(self, 20) tk.Label(self, textvariable=self.count, width=5) \ .pack(padx=5, pady=5, side=tk.LEFT) tk.Button(self, text="Destroy All Popups", command=self.destroy_popups) \ .pack(padx=5, pady=5, side=tk.LEFT) tk.Button(self, text="Create New Popup", command=self.popup) \ .pack(padx=5, pady=5, side=tk.LEFT) def popup(self): """Create a popup window""" id = len(self.popups) popup = PopupWindow(self, self.count") self.popups.append(popup) x = (id % 5) * 120 y = (id // 5) * 120 popup.geometry(f"{120}x{120}+{x}+{y}") def destroy_popups(self): """Destroy all the popup windows""" for pop in self.popups: pop.destroy() self.popups = [] RootWindow().mainloop() RE: Can't update label in new tk window, object has no attribute - tompranks - Aug-30-2022 Both works perfectly, thank you very much for all your help. Cheers! |