Search code examples
pythonclassobjecttkinterpython-multithreading

Tkinter GUI Won't Start - Thread - Tkinter object has no attribute 'Label'


I have a Tkinter GUI, which I have copy pasted from one of my other files.

The two GUI's are exact copies, 1:1. The first one works, the second doesn't.

This is the second file, with the TKinter GUI:

import mysql.connector
import threading
import tkinter as tk
import pip
import time
import mysql.connector
from time import sleep

global score
global countdown

en = "1"
score = 0
countdown = 1
tidMål = 0
tidScoreNu = 0
print("Hiya!")

mydb = mysql.connector.connect(
    host="",
    user="",
    password="",
    database='',
    auth_plugin=''
)

mycursor = mydb.cursor(prepared=True)


#MysQl commands til at interface det hele
class Mysql(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True
        self.en = 1
        self.læsTidScoreNu = "SELECT tidSCoreNu FROM bois WHERE id = 1"
        self.læsTidMål = "SELECT tidMål FROM bois WHERE id = 1"
        self.opdaterTidMål = "UPDATE bois SET tidMål = %s WHERE id = %s"
        self.læsStopKnap = "SELECT stopKnap FROM bois WHERE id = 1"
        self.run()

    def run(self) -> None:
        global mycursor
        global mydb

        mycursor.execute(self.læsTidScoreNu)
        self.råTidScoreNu = mycursor.fetchone()
        self.tidScoreNu = float("{}".format('%.2f' % self.råTidScoreNu))
        mycursor.execute(self.læsTidMål)
        self.råTidMål = mycursor.fetchone()
        self.tidMål = float("{}".format('%.2f' % self.råTidMål))
        mycursor.execute(self.læsStopKnap)
        self.stopKnap = mycursor.fetchone()

        mydb.commit()


#Control GUI til admin portalen
class Tkinter(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True
        self.root = 0
        self.entry = 0
        self.label = 0
        self.button = 0
        self.timerValue = 2
        self.stopButton = 0
        self.start()
        self.spilSlut = 0

    def run(self) -> 0:
        self.root = tk.Tk()
        global countdown

        #Baggrund
        self.root.geometry("+2+0")
        self.root.config(background="Grey")

        #Timervalue selectors
        self.label = tk.Label(self.root, bg="white", fg="black", font=("Fixedsys", 28))
        self.entry = tk.Entry(self.root, bg="white", fg="black", font=("Fixedsys", 28))

        #Start/Stop Knapper
        self.stopTiden = tk.Button(self.root, bg="red", fg="white", text="Stop Spillet", command=self.stopTid)
        self.startTiden = tk.Button(self.root, bg="green", fg="white", text="Start Spillet", command=self.startTid)

        #Timeren
        self.timerDisplay = tk.Label(self.root, bg="black", fg="red", text="Spillet er ikke startet")

        self.timerDisplay.grid(row=2, column=50)
        self.startTiden.grid(row=0, column=1)
        self.stopTiden.grid(row=0, column=10)
        self.entry.grid(row=1, column=1)
        self.label.grid(row=1, column=10)

        self.root.bind("<KeyPress>", self.read)
        self.Update(self)
        self.root.mainloop()

    def read(self, event):
        key = event.keysym
        try:
            if key == "Return":
                self.getA()
                self.visTid()
        except:
            self.fejlTidvalg()

    def startTid(self):
        self.stopButton = 0


    def getA(self):
        try:
            self.timerValue = float(self.entry.get().format("%.2f", 1.23456))
            print(self.timerValue)
            return self.timerValue
        except:
            print(fejl)

    def stopTid(self):
        self.stopButton = 1
        print("Spillet er stoppet nu")

    def visTid(self):
        self.label.config(text="Det her er timerens slutværdi: {}".format(self.timerValue))

    def fejlTidvalg(self):
        self.label.config(text="FEJL -Vælg Venligst Et Tal")

    def opdaterCountdown(self):
        if self.stopButton != 1:
            self.spilSlut = 0
            self.tidTilbage = self.timerValue - countdown
            self.tidTilbage_minutter = int(self.tidTilbage/60)
            self.tidTilbage_sekunder = (self.tidTilbage) - (self.tidTilbage_minutter * 60)
            self.timerDisplay.config(text="{} minutter, {:.2f} sekunder tilbage".format(self.tidTilbage_minutter, self.tidTilbage_sekunder))
            if self.tidTilbage < 0 or self.tidTilbage == 0 and self.timerValue > 0:
                self.spilSlut = 1

        elif self.stopButton == 1:

            self.timerDisplay.config(text="Spillet er sat på pause")

    def opdaterCountdownSpilSlut(self):
            self.timerDisplay.config(text="Spillet er slut")

    class Update(threading.Thread):
        def __init__(self, tkinter):
            threading.Thread.__init__(self)
            self.daemon = True
            self.tkinter = tkinter
            self.start()

        def run(self) -> None:
            while True:
                time.sleep(0.1)
                self.tkinter.opdaterCountdown()
                if self.tkinter.spilSlut == 1:
                    self.tkinter.opdaterCountdownSpilSlut()
                    time.sleep(1)


tk = Tkinter()

data = Mysql()


while True:
    print()

The error I get is this:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\Mandem\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:/Users/Mandem/AppData/Local/Programs/Python/Python38-32/Lib/site-packages/mysql/connector/PC-ADMIN-Camper.py", line 81, in run
    self.label = tk.Label(self.root, bg="white", fg="black", font=("Fixedsys", 28))
AttributeError: 'Tkinter' object has no attribute 'Label'

I have been looking around the forum for solutions, and it usually turns out to be something about running the function/variable before defining it. Thing is, I HAVE defined it before running it, and, the exact same code runs perfectly well in my first program.

GUI from my first program:

    import threading
import tkinter as tk
import pip
import time
import mysql.connector
from time import sleep

global score
global countdown

en = "1"
score = 0
countdown = 1
print("Hiya!")


class Tkinter(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True
        self.root = 0
        self.entry = 0
        self.label = 0
        self.button = 0
        self.timerValue = 2
        self.stopButton = 0
        self.start()
        self.spilSlut = 0

    def run(self) -> 0:
        self.root = tk.Tk()
        global countdown

        #Baggrund
        self.root.geometry("+2+0")
        self.root.config(background="Grey")

        #Timervalue selectors
        self.label = tk.Label(self.root, bg="white", fg="black", font=("Fixedsys", 28))
        self.entry = tk.Entry(self.root, bg="white", fg="black", font=("Fixedsys", 28))

        #Start/Stop Knapper
        self.stopTiden = tk.Button(self.root, bg="red", fg="white", text="Stop Spillet", command=self.stopTid)
        self.startTiden = tk.Button(self.root, bg="green", fg="white", text="Start Spillet", command=self.startTid)

        #Timeren
        self.timerDisplay = tk.Label(self.root, bg="black", fg="red", text="Spillet er ikke startet")

        self.timerDisplay.grid(row=2, column=50)
        self.startTiden.grid(row=0, column=1)
        self.stopTiden.grid(row=0, column=10)
        self.entry.grid(row=1, column=1)
        self.label.grid(row=1, column=10)

        self.root.bind("<KeyPress>", self.read)
        self.Update(self)
        self.root.mainloop()

    def read(self, event):
        key = event.keysym
        try:
            if key == "Return":
                self.getA()
                self.visTid()
        except:
            self.fejlTidvalg()

    def startTid(self):
        self.stopButton = 0


    def getA(self):
        try:
            self.timerValue = float(self.entry.get().format("%.2f", 1.23456))
            print(self.timerValue)
            return self.timerValue
        except:
            print(fejl)

    def stopTid(self):
        self.stopButton = 1
        print("Spillet er stoppet nu")

    def visTid(self):
        self.label.config(text="Det her er timerens slutværdi: {}".format(self.timerValue))

    def fejlTidvalg(self):
        self.label.config(text="FEJL -Vælg Venligst Et Tal")

    def opdaterCountdown(self):
        if self.stopButton != 1:
            self.spilSlut = 0
            self.tidTilbage = self.timerValue - countdown
            self.tidTilbage_minutter = int(self.tidTilbage/60)
            self.tidTilbage_sekunder = (self.tidTilbage) - (self.tidTilbage_minutter * 60)
            self.timerDisplay.config(text="{} minutter, {:.2f} sekunder tilbage".format(self.tidTilbage_minutter, self.tidTilbage_sekunder))
            if self.tidTilbage < 0 or self.tidTilbage == 0 and self.timerValue > 0:
                self.spilSlut = 1

        elif self.stopButton == 1:

            self.timerDisplay.config(text="Spillet er sat på pause")

    def opdaterCountdownSpilSlut(self):
            self.timerDisplay.config(text="Spillet er slut")

    class Update(threading.Thread):
        def __init__(self, tkinter):
            threading.Thread.__init__(self)
            self.daemon = True
            self.tkinter = tkinter
            self.start()

        def run(self) -> None:
            while True:
                time.sleep(0.1)
                self.tkinter.opdaterCountdown()
                if self.tkinter.spilSlut == 1:
                    self.tkinter.opdaterCountdownSpilSlut()
                    time.sleep(1)


app = Tkinter()

How come the same (exact same) GUI works in the first, but not in the second?

Have I made a typo, that I for some reason cannot find? Or is there something else I have missed?


Solution

  • The two GUI's are exact copies, 1:1.

    That is a false statement. One does app = Tkinter() and the other does tk = Tkinter().

    You are using tk for two different things:

    import tkinter as tk
    ...
    tk = Tkinter()
    

    You need to change that last line to use a different variable name.