Tkinter

  • Guten Tag!

    Ich beschäftige mich gerade mit tkinter.....

    Eine kleine Routine soll mir zwei Zustände anzeigen. "in progress" und ein paar Sekunden später "done".

    Allerdings wird immer nur "done" angezeigt, also der erste Eintrag ignoriert. Warum? Kann mir da jemand helfen?

    Zuerst hatte ich für den Zeitverzug sleep(5) genutzt, aber später den Delay durch eine while-Schleife erzeugt, weil ich den Hinweis bekommen hatte, dass es möglicherweise an sleep() liegen könnte, was aber wohl nicht der Fall ist.

    Ich sage schon einmal DANKE.

  • Bei mir funktionier der Code wie gewollt.

    Nach kurzer Zeit

    Funktioniert es mit einem sleep bei dir? Wenn ja würde ich dies nutzen. Es kann durchaus sein das je nach Einstellungen Python bei dir erkennt das die While Schleife Unsinn ist und diese einfach überspringt weil dort nicht passieren kann. Jeder Compiler würde diesen Absatz auch rauswerfen weil in der Schleife nichts passieren kann was nicht schon klar ist bevor die Schleife abgearbeitet wird.

    Code
            u=100000000
            i=0
            
            while i<u:
                i=i+1

    ist sinnloser Code, bei einer Optimierung wird ein Compiler und auch Python je nach Einstellung bereits sagen: in der Schleife passiert nichts und i wird nie gebraucht. Also wird der Abschnitt einfach übersprungen weil ohne Sinn und Nutzen. Damit fällt dann natürlich deine gewünschte Wartezeit weg.

    Einmal editiert, zuletzt von InterGeek (20. Januar 2022 um 17:04)

  • Hallo Francisca

    nach dem Beispiel in meinem zweiten Link (in dem anderen Beitrag )

    http://www.nemoquiz.com/python/tkinter-time-delay/

    habe ich Deinen Code angepasst:

    Bei mir läuft er so...

  • Ah....sleep und "mein while-Schleife funktionieren. D.H. ein Delay wird erzeugt.

    Aber das ist nicht mein Problem.

    Mein Problem ist, dass in meinem Progrämmchen "in progress" nie angezeigt wird.

  • Hast du eine Erklärung dafür, dass es in meinem Programm nicht funktioniert?

    Es kann durchaus sein das dein Programm durch die Schleife beschäftigt war und nicht mehr dazu gekommen ist die neuen Informationen anzuzeigen. Wenn es wieder Zeit hatte wäre der Wechsel so schnell dass du ihn nicht mehr sehen würdest.

  • Tkinter ist single-threaded.

    Mit einem time.sleep() wartet das ganze Programm, inklusive der mainloop().

    So wird auch die Anzeige nicht mehr aufgefrischt um das "in progress" anzuzeigen.

    Erst nach der sleep()-Zeit geht es weiter, dann halt direkt mit "done".

  • Hallo,

    GUI's programmiert man so nicht. Schleifen in der GUI unterbrechen die 'mainloop'. Gleiches gilt für 'sleep'. Dein Programm "fühlt" sich dann an, als wäre es eingefroren.

    'tkinter' hat dafür die 'after'-Methode. Damit kann man solche Sachen realisieren.

    Du wirst auch ohne objektorientierte Programmierung relativ schnell an die Grenzen der GUI-Programmierung kommen. Das heißt, du musst dich mit Klassen beschäftigen.

    Grundsätzliches:

    Verwende keine *-Importe, damit holst du dir alle Namen von 'tkinter' in deinen Namensraum. Das kann zu Namenskollisionen, schwere Fehlersuche und unübersichtlichen Code führen.

    Auf Modulebene (der Code ohne Einrückungen) soll kein ausführbarer Code stehen. Hier werden nur Klassen, Funktionen und Konstanten definiert.

    Die GUI-Elemente erstellt man zu Beginn des Programms.

    Verwende sprechende Namen und keine Abkürzungen wie 'u', 'i', 'XPOS' etc. Funktionsnamen beschreiben was eine Funktion macht, wenn man sie 'anzeige' nennt, dann sollte es entweder eine Klasse sein, der Name ist falsch oder der Inhalt der Funktion ist nicht sauber getrennt. So wie auch hier, zum einen werden GUI-Elemente erstellt und zum anderen wird eine Zahl hochgezählt.

    Man erstellt auch nicht ein Label über einem anderen Label um den Text zu ändern, das kann man mit 'configure' des erstellten Labels machen.

    Das sind jetzt ein paar Infos für dich und den passenden Code reiche ich dir nach, versprochen.

    Mach dich mit 'after' vertraut und vergess die Schleifen in einem 'tkinter'-GUI.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • ist sinnloser Code, bei einer Optimierung wird ein Compiler und auch Python je nach Einstellung bereits sagen: in der Schleife passiert nichts und i wird nie gebraucht. Also wird der Abschnitt einfach übersprungen weil ohne Sinn und Nutzen. Damit fällt dann natürlich deine gewünschte Wartezeit weg.

    Nein, es wird nicht wegoptimiert.

    Ansonsten könnte man auch keine busy_loop machen:

    Code
    while True:
        pass
    Code
    [deadeye@nexus ~]$ time python busy_loop.py 
    
    real    0m5,232s
    user    0m5,217s
    sys     0m0,017s
    Python: busy_loop.py
    u = 100_000_000
    i = 0
    while i < u:
        i += 1

    Genauso gut könnte man ein sleep einbauen, um eine Wartezeit zu erzielen, ohne einen Kern auf 100 % zu belasten.

    Geht aber nicht, da eine GUI verwendet wird und durch die busy_loop oder durch ein sleep die Eventloop der GUI blockiert wird.

  • Danke für eure Antworten und eure Mühe!

    Ich denke, ich habe mit meinem Delay eine falsche Fährte gelegt.

    Ich habe eine Routine programmiert, die eine 7-Segment-Anzeige mit Hilfe eines Raspberry ansteuert.

    Um mein Problem deutlich zu machen, habe ich diese Routine abgeändert, um nicht abzulenken. Offensichtlich ist mir das nicht gelungen, sondern habe nur alle verwirrt. Sorry!

    Darum stelle ich euch jetzt das ganze Programm ein. Ich habe die Display-Ansteuerung ersetzt durch print-Anweisungen, damit das Programm auch auf einem Computer läuft. Über die Eingabemaske sollen die Anzahl der Durchläufe und die Dauer der Darstellung eingegeben werden können. Solange dann die Darstellung der Zahlen läuft (auf dem Computer print(), auf dem Raspberry die 7_Segmentanzeige), soll in der Maske neben Process ("in progress") und nach dem Durchlaufen aller Routinen "done" stehen.

    Wenn ihr das Programm ausführt, wird "in progress" nicht dargestellt, "done" am Ende aber schon.

  • Hallo,

    du hast egal wie du es drehst und wendest das gleiche Problem. Bleib ruhig mal bei deinem vereinfachten Beispiel. Les dir bitte noch mal mein Text durch und hier ist der versprochene Code dazu:

    Wie du gleich siehst, ziemlich unübersichtlich. Das liegt an den Umwegen die man ohne objektorientierte Programmierung machen muss. Versuche das mal nachzuvollziehen.

    Bitte verwende den Code nicht um ein aufwendigeres GUI zu erstellen, das wird vermutlich nicht funktionieren.

    Mit diesem Tutorial kannst du die in Klassen einarbeiten.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Nachtrag: Hier wäre noch ein objektorientierter Ansatz

    Bitte poste deine Codes direkt ins Forum mit dem </> - Button. So kann man sich das gleich anschauen, auch wenn man am Handy etc. ist.

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!