Labels werden nicht angezeigt

Fragen zu Tkinter.
Antworten
Shiny Emerald
User
Beiträge: 8
Registriert: Samstag 13. Juli 2019, 09:49

Hallo zusammen,

ich habe eine Frage zu tkinter. Und zwar programmiere ich gerade ein Quiz mit tkinter und mein Problem ist, dass mir meine Labels nicht angezeigt werden. Buttons werden angezeigt aber die Fragen und Antworten leider nicht. Hier ein Beispiel für ein Label, welches in meinem Quiz vorkommt:

lbl = Label(fenster, text = "Wie lautet die Atomaremasse 1 u in Kilogramm?", font=("Arial Bold", 14) )
lbl.grid(column=0, row=4)

Das Fenster hat sich geöffnet, knöpfe wurden angezeigt aber die Label nicht.
Ich habe das

fenster.mainloop()

auch nicht vergessen. Was mache ich falsch?
Danke für eure Hilfe.

Shiny
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Shiny Emerald: Du machst irgend etwas falsch was man im gezeigten Code nicht sehen kann.

Was auf jeden Fall komisch aussieht ist das Du für eine konkrete Frage ein `Label` erstellst. Man erstellt üblicherweise einmal *ein* `Label` für Fragen und zeigt in diesem einen `Label` dann im Laufe des Programms die verschiedenen Fragen an.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Shiny Emerald
User
Beiträge: 8
Registriert: Samstag 13. Juli 2019, 09:49

@__blackjack__: Also ich hab's jetzt so gemacht und die Labels werden immer noch nicht angezeigt.


Code: Alles auswählen

import random
from tkinter import *

window = Tk()
window.title = ("Quiz")
window.geometry("600x450")

questions = [["Wie lang ist der Nil?", "4936 km", "532 km", "9348 km", "6852 km"]]
questions.append(["Was ist die für den Körper gefährlichste Droge?", "LSD", "Canabis", "Pilze", "Alkohol"])
questions.append(["Mit welcher Programmiersprache wurde dieses Quiz programmiert?", "Java", "C++", "Delphi", "Python"])
questions.append(["Wie kalt ist flüssiger Stickstoff?", "-87° C", "-219° C", "-678° C", "-196° C"])
questions.append(["Aus was besteht Licht nicht?", "Wellen", "Energie", "Teilchen", "Strom"])
questions.append(["Wer erfand Python?", "Albert Einstein", "Steve Jobs", "James Gosling", "Guido van Rossum"])
questions.append(["Wie warm ist die Sonne im Kern", "15000° C", "1600° C", "4500000000° C", "15000000° C"])

def clear():
    list = window.grid_slaves()
    for n in list:
        n.destroy()

class Quiz:
        def __init__(self,quest):
                clear()
                self.Fragen = []
                for n in quest:
                        self.Fragen.append(n)
                self.a1=""
                self.a2=""
                self.a3=""
                self.a4=""
                self.Ra=""
                self.RaBtn = Button(window, text="",font=("Arial", 14))
                self.antw1 = Button(window, text="",font=("Arial", 14))
                self.antw2 = Button(window, text="",font=("Arial", 14))
                self.antw3 = Button(window, text="",font=("Arial", 14))
                self.antw4 = Button(window, text="",font=("Arial", 14))
                self.lock=False
                self.right=0
                self.next = Button(window,text="Next Question",font=("Arial", 14),command=self.Frage)
                self.nummer=0
                self.Max=3
                self.Frage()
        def Frage(self):
                self.next.grid(column=0,row=5,pady=5)
                if len(self.Fragen) > 0 and self.nummer < self.Max:
                        self.nummer += 1
                        self.lock = False
                        randomNum = random.randint(0, len(self.Fragen)-1)
                        fragenText = self.Fragen[randNum][0]
                        self.Ra = self.Fragen[randNum][randNum][-1]
                        answers = []
                        for i in range(1,5):
                                answers.append(self.Fragen[randNum][i])

                        self.a1 = answers[0]
                        self.a2 = answers[1]
                        self.a3 = answers[2]
                        self.a4 = answers[3]

                        frage = Text(window, font=("Arial", 14), width=40, height=2)
                        frage.insert(END,fragenText)
                        frage.grid(column=0,row=0,padx=80, pady=(75,0))

                        self.antw1 = Button(window, text=self.a1, font=("Arial", 14),width=39,command = self.control1)
                        self.antw2 = Button(window, text=self.a2, font=("Arial", 14),width=39,command = self.control2)
                        self.antw3 = Button(window, text=self.a3, font=("Arial", 14),width=39,command = self.control3)
                        self.antw4 = Button(window, text=self.a4, font=("Arial", 14),width=39,command = self.control4)

                        self.antw1.grid(column=0,row=1,pady=(8,5))
                        self.antw2.grid(column=0,row=2,pady=(5))
                        self.antw3.grid(column=0,row=3,pady=(5))
                        self.antw4.grid(column=0,row=4,pady=(5))

                        if self.a1 == self.Ra:
                                self.RaBtn = self.antw1
                        elif self.a2 == self.Ra:
                                self.RaBtn = self.antw2
                        elif self.a3 == self.Ra:
                                self.RaBtn = self.antw3
                        elif self.a4 == self.Ra:
                                self.RaBtn = self.antw4
                        self.Fragen.pop(randNum)

                else:
                        clear()
                        lb = label(window, text="Du hast " + str(self.right) + "von " + str(self.Max) + "Fragen richtig beantwortet", font=("Arial", 14))
                        lb.grid(column=0,row=0,padx=120,pady=(170,15))
                        zumMenu = Buttin(window, text="Menu",font=("Arial", 14),command=menuCreator)
                        zumMenu.grid(column=0,row=1)
        def control1(self):
                if self.lock == False:
                        if self.Ra != self.a1:
                                self.antw1.configure(bg="red")
                        else:
                                self.antw1.configure(bg="green")
                                self.right += 1
                        self.RaBtn.configure(bg="green")
                        self.lock = True

        def control2(self):
                if self.lock == False:
                        if self.Ra != self.a2:
                                self.antw2.configure(bg="red")
                        else:
                                self.antw2.configure(bg="green")
                                self.right += 1
                        self.RaBtn.configure(bg="green")
                        self.lock = True

        def control3(self):
                if self.lock == False:
                        if self.Ra != self.a3:
                                self.antw3.configure(bg="red")
                        else:
                                self.antw3.configure(bg="green")
                                self.right += 1
                        self.RaBtn.configure(bg="green")
                        self.lock = True

        def control4(self):
                if self.lock == False:
                        if self.Ra != self.a4:
                                self.antw4.configure(bg="red")
                        else:
                                self.antw4.configure(bg="green")
                                self.right += 1
                        self.RaBtn.configure(bg="green")
                        self.lock = True
                
                        

class Menu:
    def __init__(self):
        clear()
        self.Quiz = Button(window, text="Start", font=("Arial", 14), command=quizCreator, width=15, height=3)

        self.Quiz.grid(column=0,row=0,padx=218,pady=170)

def menuCreator():
    m = Menu()

def quizCreator():
    q = Quiz(questions)

menuCreator()
window.mainloop()

Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich möchte in Deinem Code gar nicht suchen, wo der Fehler liegt, denn so programmiert man eine GUI nicht.
Statt ständig Knöpfe zu erzeugen und wieder zu zerstören, solltest Du einmal die Elemente Deines Fensters aufbauen, und nur jeweils den Text der Knöpfe ändern.

Falls Du tatsächlich dynamisch Inhalte austauschen willst, definierst Du Dir Frames, die Du entfernen könntest, ein Start-Frame, ein Quiz-Frame. Damit wird die Funktion `clear` überflüssig.

Zum Code: Sternchenimporte vermeiden. Tkinter wird üblicherweise als "import tkinter as tk" importiert und alle Namen per tk.xyz angesprochen. Benutze keine globalen Variablen, das erzeugen von `window` ebenso wie die letzten beiden Zeilen gehören in eine Funktion, die üblicherweise `main` genannt wird.

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 4 und mal 8.
Wenn Du eine Kopie einer Liste haben möchtest, geht das über `self.Fragen = list(quest)`. Vermeide aber Abkürzungen. `quest` -> questions und vermeide Deutsch/Englisch-Mischung, also statt Fragen questions.
Wenn Du anfängst, Namen durchzunummerieren, willst Du eigentlich Listen verwenden.
answers ist ja schon eine Liste, a1..a4 ist also unnötig. Achso, keine Abkürzungen, Ra wird wohl right_answer heißen.

`control1`, `control2`, usw. tun alles das selbe, sind also eigentlich eine Methode, die einen Parameter mit dem passenden Knopf bekommt. Oder besser noch, in einer Methode alle vier Knöpfe auf disable setzen, dann brauchst Du auch kein `lock`.

Variablen sollten nicht mit Dummy-Werten belegt werden, wie es in Quiz.__init__ der Fall ist. Es kann manchmal sinnvoll sein, einen Defaultwert einem Attribut zuzuweisen, dann ist das `None`.

Variablennamen, Methoden und Funktionen schreibt man nach Konvention klein_mit_unterstrich.
Man prüft nicht explizit auf `False` sondern benutzt `not self.lock`.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Shiny Emerald: Sternchen-Importe sind Böse™. Du holst Dir da bei `tkinter` über 190 Namen ins Modul von denen a) nur ein Bruchtteil benötigt wird, und b) nicht nur welche die in dem Modul definiert sind, sondern auch welche die `tkinter` seinerseits importiert.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Das hat dann zur Folge das `window` beispielsweise nicht mehr einfach so auf magische Weise überall verwendet werden kann, sondern ordentlich als Argument übergeben werden muss.

Eingerückt wird mit vier Leerzeichen pro Ebene.

Die ganzen `questions.append()`-Aufrufe sind unnötig umständlich. Warum schreibst Du das alles nicht einfach als *ein* Listenliteral da hin?

Namen werden in Python klein_mit_unterstrichen geschrieben, ausgenommen Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

`menuCreator()` und im Grunde auch `quizCreator()` sind überflüssig. Die jeweiligen einbuchstabigen lokalen Namen in den Funktionen ebenfalls. Ein Buchstabe ist auch selten ein guter, beschreibender Namen. Ebenso sollte man Namen weder kryptisch abkürzen, noch durchnummerieren. Nummerierte Namen sind in aller Regel ein Zeichen, dass man sich bessere Namen ausdenken sollte, oder das man gar keine einzelnen Namen für die Werte haben möchte, sondern nur einen für die Datenstruktur in die man die Werte stecken sollte. Oft ist das eine Liste.

Die Namen der Funktionen passen auch nicht so richtig zu Funktionen, denn Funktionen und Methoden werden üblicherweise nach der Tätigkeit benannt, die sie beschreiben um sie von eher passiven Werten unterscheiden zu können.

„Cannabis“ schreibt man mit Doppel-„n“. Die Antwort bei der dazugehörigen Frage ist IMHO auch inhaltlich falsch, auch ohne dazu irgendwelche Studien gelesen zu haben, weil es mit *Sicherheit* mindestens eine Pilzart gibt, die als Droge verwendet werden kann *und* gefährlicher als alles andere auf der Liste ist.

`control1()` bis `control4()` enthalten nahezu identischen Code, das sollten nicht vier Methoden sein, sondern eine.

Schlag mal die Bedeutung von `quest` nach. Wenn Du `questions` meinst – wie gesagt, Abkürzungen sind doof. Namen sollen dem Leser vermitteln was ein Wert bedeutet, und ihn weder in die Irre führen, zum zum Raten zwingen.

``random.randint(0, len(self.Fragen)-1)`` ist unnötig umständlich für ``random.randrange(0, len(self.Fragen)), aber *eigentlich* willst Du hier `random.choice()` haben. Beziehungsweise noch besser gar nicht einzelne Fragen auswählen und aus der Liste entfernen, sondern die Liste am Anfang einmal mit `random.shuffle()` mischen und dann einfach der Reihe nach durchgehen. Dann braucht man die Frage auch nicht zwingend in eine neue Liste umkopieren aus der man sie dann nach und nach löscht.

Was da grundsätzlich falsch läuft ist das Du die GUI zu sehr veränderst im Laufe des Programms. Die wird normalerweise *einmal* mit allen Elementen aufgebaut, und die *bleiben* dann, und werden nur entsprechend verändert. So etwas wie die `clear()`-Funktion macht man nicht.

Ich sehe so auf Anhieb nicht warum das *eine* Label nicht angezeigt werden sollte, sehe kurz darauf aber einen `NameError` – warum hast Du uns den nicht verraten?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten