Tkinter UnboundLocalError

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Boruto_2200
User
Beiträge: 8
Registriert: Montag 21. Dezember 2020, 14:15

Hey Leute, ich hätte da eine Frage...
Ich schreibe gerade einen CPS-Tester mit Tkinter, aber immer, wenn ich ihn starte, zeigt er mir "UnboundLocalError: local variable 'CPS' referenced before assignment" an. Ich verstehe das einfach nicht... Ich programmiere jetzt schon ca. 1 Jahr mit Python, und so etwas ist mir eigentlich noch nie passiert... :| Wäre gut, wenn mir einer helfen könnte...

Hier noch der ganze Code:

from tkinter import *

window = Tk()
c = Canvas(window, width = 800, height = 800)
c.pack

CPS = 0

def CPSclock():
CPS = CPS + 1

cps_button = Button(window, text = 'Click Me!', width = 500, height = 150, command = CPSclock)
cps_button.pack()

mainloop()

Vielen Dank :D
miel9
User
Beiträge: 12
Registriert: Freitag 21. Juni 2019, 13:19

Soweit Funktioniert das:

Code: Alles auswählen

from tkinter import *

window = Tk()
c = Canvas(window, width = 1, height = 1)
c.pack

cps = 0

def CPSclock():
    global cps 
    cps += 1

cps_button = Button(window, text = 'Click Me!', width = 500, height = 150, command = CPSclock)
cps_button.pack()
b = Button(window, text='A', command=pr).pack()

mainloop()
Bei dir hatte das wegen Python's Globale-und-Lokale-Variablen-Generve nicht Funktioniert. Das hat mich auch schon mehrmals in den Wahnsinn getrieben :D .
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Boruto_2200: Vergiss ``global`` gleich wieder. Das schafft mehr Probleme als es löst.

Wenn man in einer Funktion/Methode eine Zuweisung an einen Namen hat, dann ist das ein lokaler Name. `CPS` in `CPSclock()` ist also ein lokaler Name der nichts mit dem Namen `CPS` auf Modulebene zu tun hat.

`CPS` auf Modulebene sollte es auch gar nicht geben. Genau wie alles andere was da ausser dem Import und der Funktionsdefinition steht. Das Hauptprogramm gehört in eine Funktion. Üblicherweise wird die `main()` genannt.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Funktions- und Methodennamen werden üblicherweise nach der Tätigkeit benannt die sie durchführen. Damit kann man sie besser von eher ”passiven” Werten unterscheiden.

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 200 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Bei jeder nicht-trivialen GUI braucht man objektorientierte Programmierung. Also eigene Klassen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

*-Importe sollte man nicht verwenden. c.pack sollte man aufrufen. Variablennamen sollten aussagekräftig sein. Und für Zustand in GUIs braucht man Klassendefinitionen.

Code: Alles auswählen

import tkinter as tk

class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.canvas = tk.Canvas(self, width=800, height=800)
        self.canvas.pack()
        tk.Button(self, text='Click Me!', width=500, height=150, command=self.cps_clock).pack()
        self.cps = 0
        
    def cps_clock(self):
        self.cps += 1

def main():
    window = MainWindow()
    window.mainloop()

if __name__ == '__main__':
    main()
Boruto_2200
User
Beiträge: 8
Registriert: Montag 21. Dezember 2020, 14:15

Vielen Dank für eure schnelle Hilfe :D

Jetzt habe ich aber ein weiteres Problem: Nämlich die ständige Ausgabe des Wertes 'cps'...
Ich habe schon getan, was ich konnte, aber es funktioniert nicht wirklich... Ich habe einen Exitbutton gemacht, mit dem man das Programm beenden kann; vorher bekommt man aber über das Shell den Wert 'cps' ausgegeben. Das Problem ist die Ausgabe von den cps; Es soll jede Sekunde die CPS der vergangenen Sekunde geben und die durchschnittliche cps ca. alle 5 sek aktualisieren. Ich habe jetzt schon einiges ausprobiert, das ganze hat aber nicht funktioniert....
Hier wäre noch der aktuelle Code:

Code: Alles auswählen

from tkinter import *

window = Tk()
c = Canvas(window, width = 1, height = 1)
c.pack

cps = 0

def pr():
    global cps 
    cps += 1

def exitx():
    text = 'CPS: ' + str(cps)
    print(text)
    window.destroy()
    
b = Button(window, text='A', command=pr).pack()

exit_ = Button(window, text = 'Exit', command = exitx).pack()

mainloop()
Antworten