x.config funktioniert nicht

Fragen zu Tkinter.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Guten Morgen,

ich möchte mir TKinter etwas genauer anschauen. Dazu habe ich im Netz diese Seite gefunden:
http://www.python-kurs.eu/tkinter_labels.php

In diesem Abschnitt geht es um Labels. Weiter unten unter der Überschrift "Dynamischer Inhalt in einem Label-Widget" gibt es ein kleines Beispiel mit einem Counter. In diesem Beispiel gibt es einen Befehl (in Funktion "counter_label"), welcher bei meinem MacBook nicht funktioniert. Bei Windows funktioniert er problemlos. Bei beiden Betriebssystemen habe ich es nochmal per Copy&Paste versucht, um Tippfehler auszuschließen.

Die besagte Zeile lautet: label.config(text=str(counter))

Beim Mac bekomme ich die Meldung, dass .config nicht in der Bibliothek vorhanden wäre.

Weiß hier jemand weiter ?

Grüße,
lordzwieback
BlackJack

@lordzwieback: Zeig mal bitte den kompletten Quelltext der diesen Fehler zur Folge hat und auch den kompletten Traceback dazu. Das sollte nicht passieren.

Allerdings ist der Quelltext auf der verlinkten Seite nicht wirklich schön mit dem ``global``.
eckhard
User
Beiträge: 33
Registriert: Montag 14. Dezember 2015, 10:06
Wohnort: Karlsruhe

@lordzwieback: Steht vor config vielleicht ein Komma statt einem Punkt?
Ein solcher Tippfehler ist mir schon oft passiert.

eckhard
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Hey, sorry das ich jetzt erst antworte, bin eben erst heimgekommen.

Der komplette Code:

Code: Alles auswählen

from tkinter import *

counter = 0

def counter_label(label):
    def count():
        global counter
        counter += 1
        label.config(text=str(counter))
        label.after(1000, count)
    count()

root = Tk()
root.title("Counting seconds")
label = Label(root, fg="green").pack()
counter_label(label)
button = Button(root, text="stop", width=25, command=root.destroy()).pack()

root.mainloop()

Und der Traceback dazu:

Code: Alles auswählen

/Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4 /Users/***/PycharmProjects/tkinter/count_seconds.py
Traceback (most recent call last):
  File "/Users/***/PycharmProjects/tkinter/count_seconds.py", line 16, in <module>
    counter_label(label)
  File "/Users/***/PycharmProjects/tkinter/count_seconds.py", line 11, in counter_label
    count()
  File "/Users/***/PycharmProjects/tkinter/count_seconds.py", line 9, in count
    label.config(text=str(counter))
AttributeError: 'NoneType' object has no attribute 'config'

Process finished with exit code 1
Sorry falsch ich den Traceback falsch interpretiert hab.
BlackJack

@lordzwieback: Der Code würde unter Windows die gleiche Ausnahme zur Folge haben. Lass Dir `label` mal ausgeben und wenn Du schon dabei bist auch `button`. Und dann schau Dir den Unterschied zu der verlinkten Webseite an und was *dort* an die Namen gebunden wird.
lordzwieback
User
Beiträge: 55
Registriert: Montag 2. März 2015, 14:35
Kontaktdaten:

Alles klar, hab die Fehler gefunden, danke. War wohl blind vom vielen Draufglotzen..
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Der letzte Beitrag ist zwar älter, aber ich haba das gleiche Problem und komme leider nicht auf die Lösung. :-(
Es wäre nett, wenn das noch jemand kurz erklären könnte.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Auch fuer dich gilt, was fuer lordzwieback gilt: zeig deinen Code. Ohne den kann man dazu nichts sagen.
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Code: Alles auswählen

from tkinter import *
from tkinter import messagebox
from time import sleep

fehlversuche = 0
global lockedTime
lockedTime=0


variablen = {}

root2 = Tk()
w, h = 800, 800
root2.geometry("%dx%d+0+0" % (w, h))
root2.configure(bg="dark red")
root2.resizable(width=0, height=0)
canvas_width = w
canvas_height = h

variablen = {"fehlversuche": fehlversuche, "root2": root2,"lockedTime": lockedTime}

masterPasswordVar ="1234"
 

widget1 = Label(root2, justify=LEFT, fg = "dark red", bg = "#fffacd", font = "Helvetica 32 bold italic", text="Please enter your password!").place(x=100,y=1)
widget2 = Label(root2, justify=LEFT, fg = "dark red", bg ="#00FFFF", font = "Helvetica 32 bold italic", text="!!!Wrong password!!!")




def count(var):
    widget3 = Label(root2, justify=LEFT, fg = "dark red", bg ="#00FFFF", font = "Helvetica 32 bold italic", text=str(var["lockedTime"])).place(x=100,y=60)
    while True:
        print(str(var["lockedTime"]))
        var["lockedTime"] -=1
        str(var["lockedTime"])
        widget3.config(text=str(var["lockedTime"])) # Hier ist der Fehler!
        sleep(1)
        if var["lockedTime"] ==50: # Damit die Shleife früher abbricht und ich nicht so lange warten muss
            break
        


    
def confirmMasterPass(var):
    print("LockedTime: " + str(var["lockedTime"]))
    if var["lockedTime"]==0:
        print("MasterPassword is checking...")

        if (entryMasterPassword.get()==masterPasswordVar):
            print("MasterPassword true")
            print("start mainbody...")
            root2.destroy()
            main()
            
        else:
            print("Fails: " + str(var["fehlversuche"]))
            var["fehlversuche"] += 1
            entryMasterPassword.delete(0,"end")
            print("MasterPassword false")
            widget2.place(x=220,y=340)
            
            if var["fehlversuche"] == 3:
                var["lockedTime"]=60
                
                messagebox.showerror("Passwort falsch!", "Too much fails!!! The programm is locked for 60s")
                count(var)
                
                
            else:
                messagebox.showerror(title="Informtion", message="Wrong Password")
    else:
        messagebox.showerror(title="Informtion", message="The programm is still locked for: "+ str(var["lockedTime"]))

        
        
entryMasterPassword = Entry(master=root2, bg="#fffacd")
confirmMasterPassword=Button(master=root2, text="Confirm password", command=lambda:confirmMasterPass(variablen))
exitB = Button(master=root2, text="Close programm", command=lambda: root2.destroy())

exitB.place(x=350,y=700, width=150, height=20)
entryMasterPassword.place(x=325, y=400, width=200, height=40)
confirmMasterPassword.place(x=350, y=450, width=150, height=20)

confirmMasterPassword.configure(bg="#7cfc00")
exitB.configure(bg="#7cfc00")

root2.bind("<Return>", lambda e: confirmMasterPass(variablen))


def main():
    print("succes start mainbody")
    root = Tk()

    w, h = 800, 800

    root.geometry("%dx%d+0+0" % (w, h))

    root.configure(bg="green")

    canvas_width = w
    canvas_height = h
    root.resizable(width=0, height=0)


    widget50 = Label(root, justify=LEFT, fg = "blue", bg = "#fffacd", font = "Helvetica 32 bold italic", text="Welcome back!").place(relx=0.3,y=1)
    exitB2 = Button(master=root, text="Close programm", command=lambda: root.destroy())

    exitB2.place(x=350,y=750, width=150, height=20)
    root.mainloop()




root2.mainloop()


1 Sache vorweg: Der code ist nicht perfekt, ich sitzte erst seit gestern dran und mache manche Sachen erst später.
EDIT: Danke für die schnelle Antwort. :-)
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und die Fehlermeldung?
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Tobias\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:\Users\Tobias\Desktop\python\123.py", line 90, in <lambda>
    root2.bind("<Return>", lambda e: confirmMasterPass(variablen))
  File "C:\Users\Tobias\Desktop\python\123.py", line 67, in confirmMasterPass
    count(var)
  File "C:\Users\Tobias\Desktop\python\123.py", line 37, in count
    widget3.config(text=str(var["lockedTime"])) # Hier ist der Fehler!
AttributeError: 'NoneType' object has no attribute 'config'
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was ist denn der Rueckgabewert der place-Methode? Wenn du das rausgefunden hast, loest sich dein Problem.
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Wie meinst du? Wie kann ich das herausfinden?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Indem du mal in die Dokumentation zu place schaust. Oder dir den Wert auch mal einfach ausgeben laesst.
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Ich finde die Biblothek nicht. Bestimmt ist es voll einfach sie zu finden, aber dafür bin ich gerdae zu blöd. :-(
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Wo hast Du denn die Dokumentation zu tkinter gesucht?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe gerade nochmal selbst gesucht. Meine Guete. Die Dokumentation rund um tkinter ist ein solcher Cluster-Fuck, es ist schon beeindruckend.

@timm4444 du glaubst (oder behandelst es zumindest so), das place() das Widget zurueck liefern wuerde. Tut es nicht. Es liefert None. Und konsequenterweise kracht es dann.

Separier die Anlage eines Widgets von seiner Platzierung, und es funktioniert. Und dann der uebliche Hinweis: place ist Mist. Grosser Mist. Benutz es nicht, sondern bau dein Layout mit grid und pack auf (wobei man die, wie alle layout-Methoden, nicht in einem Container, also einem Fenster oder einem Frame, mischen darf).
timm4444
User
Beiträge: 51
Registriert: Samstag 1. August 2020, 14:11

Ok, danke, jetzt funtioniert es, nachdem ich noch ein "root.update()" hinzugefügt habe.
Frage: Wieso geht

Code: Alles auswählen

abc =label().place()
nicht, aber getrennt?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Habe ich doch gesagt. place liefert None zurueck. Das sagt doch auch dein Fehler.

Code: Alles auswählen

AttributeError: 'NoneType' object has no attribute 'config'
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@timm4444: Das `root.update()` ist falsch und gefährlich. GUI-Programmierung ist nicht linear, da arbeitet man mit Ereignissen. Und für jede nicht-triviale GUI kommt man um objektorientierte Programmierung (OOP) nicht herum. Also eigene Klasse(n) schreiben.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten