Python Forum
[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_label
but 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!