UnboundLocalError nicht auflösbar

Fragen zu Tkinter.
Antworten
Vicky
User
Beiträge: 5
Registriert: Mittwoch 20. Februar 2019, 12:50

Liebes Forum, ich bin Anfänger und verzweifelt. Wie bekomme ich hier den folgenden Fehler weg: UnboundLocalError: local variable 'label_welcome_index' referenced before assignment
Ich weiß, was der Fehler bedeutet, kann ihn aber nicht beheben.

(Anmerkung: seltsam, beim Einfügen des Codes in dieses Forum-Fenster verschwinden die Tabs unten den beiden Methoden "def program()" und "def zeileweiter(x)", die sind aber natürlich in meinem Originalcode drin)


from tkinter import *

TEXT = ["erste Zeile", "zweite Zeile", "dritte Zeile", "vierte Zeile"]


def programm():
fenster.config(width=100, height=100)
fenster.title("Ich bin der Titel")
label_welcome_index = 0
label_welcome_text= StringVar()
label_welcome_text.set(TEXT[label_welcome_index])
label_welcome = Label(fenster, textvariable=label_welcome_text)
label_welcome.bind("<Button-1>", zeileweiter)
label_welcome.pack()
button_end = Button(text="quit", command=fenster.quit)
button_end.pack()

def zeileweiter(x):
label_welcome_index += 1
label_welcome_index %= len(TEXT)
label_welcome.set(text=TEXT[label_welcome_index])

fenster = Tk()
programm()
fenster.mainloop()
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Tabs verschwinden nicht, sie werden nur nicht angezeigt, dafür gibt es hier im Forum Code-Tags (</> Knopf)
Eine Funktion muß alles, was sie braucht über ihre Argumente bekommen, und alles was sie ändert per Return zurückgeben. Und da fängt schon das Problem an, label_welcome und label_welcome_index kannst Du zwar als Argument übergeben, aber den geänderten Index nicht zurückgeben.

Das läßt sich aber z.b. mit cycle lösen.

Code: Alles auswählen

import tkinter as tk
from itertools import cycle
from functools import partial

TEXT = ["erste Zeile", "zweite Zeile", "dritte Zeile", "vierte Zeile"]

def programm():
    fenster = tk.Tk()
    fenster.config(width=100, height=100)
    fenster.title("Ich bin der Titel")
    rolling_text = cycle(TEXT)
    label_welcome_text= tk.StringVar()
    label_welcome_text.set(next(rolling_text))
    label_welcome = tk.Label(fenster, textvariable=label_welcome_text)
    label_welcome.bind("<Button-1>", partial(zeileweiter, label_welcome_text, rolling_text))
    label_welcome.pack()
    button_end = tk.Button(text="quit", command=fenster.quit)
    button_end.pack()
    fenster.mainloop()
    
def zeileweiter(label_welcome_text, rolling_text, _):
    label_welcome_text.set(text=next(rolling_text))

if __name__ == '__main__':
    programm()
Vicky
User
Beiträge: 5
Registriert: Mittwoch 20. Februar 2019, 12:50

Vielen Dank, das ist eine sehr interessante Lösung. Hier ist eine Variante, die meinem Code zugrunde liegt und funktioniert. Ich habe einfach nur die Klasse weggelassen und plötzlich geht der Code nicht. Warum bloß?

Code: Alles auswählen

from tkinter import *

class MyFirstGUI:
    LABEL_TEXT = [
        "This is our first GUI!",
        "Actually, this is our second GUI.",
        "We made it more interesting...",
        "...by making this label interactive.",
        "Go on, click on it again."
    ]

    def __init__(self, master):
        self.master = master
        master.title('Calculator')

        self.label_index=0
        self.label_text=StringVar()
        self.label_text.set(self.LABEL_TEXT[self.label_index])
        self.label = Label(master, textvariable=self.label_text)
        self.label.bind("<Button-1>", self.cycle_label_text)
        self.label.pack()

        self.close_button = Button(text="Beenden", command=self.master.quit)
        self.close_button.pack()

    def cycle_label_text(self, event):
        self.label_index += 1
        self.label_index %= len(self.LABEL_TEXT)
        self.label_text.set(self.LABEL_TEXT[self.label_index])
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Vicky: Weil man da nicht einfach die Klasse weglassen kann wenn dadurch Attribute zu lokalen Namen werden.

Edit: Statt die Klasse weg zu lassen, solltest Du besser den Umgang mit Klassen lernen, die die braucht man für jedes nicht-triviale GUI-Programm.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Vicky
User
Beiträge: 5
Registriert: Mittwoch 20. Februar 2019, 12:50

Halleluja und Heureka, so funktioniert es. Allen vielen Dank!

Code: Alles auswählen

from tkinter import *

TEXT = ["erste Zeile", "zweite Zeile", "dritte Zeile", "vierte Zeile"]
label_index = 0

def zeileweiter(x):
    global label_index
    label_index += 1
    label_index %= len(TEXT)
    label_welcome_text.set(TEXT[label_index])

fenster = Tk()
fenster.config(width=100, height=100)
fenster.title("Ich bin der Titel")

label_welcome_index = 0
label_welcome_text= StringVar()
label_welcome_text.set(TEXT[label_welcome_index])
label_welcome = Label(fenster, textvariable=label_welcome_text)
label_welcome.bind("<Button-1>", zeileweiter)
label_welcome.pack()

button_end = Button(text="quit", command=fenster.quit)
button_end.pack()
fenster.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Vicky: Nein! Vergiss ``global``, das hat in einem sauberen Programm nichts zu suchen. Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Da gehören keine Variablen hin!
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten