after() Funktion nur einmal möglich?

Fragen zu Tkinter.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Uuuuuund da sind wir dann im "soll-man-nicht-machen-Land". update und update_idletasks sollte man nicht selbst aufrufen. Sondern den mainloop betreten, und after verwenden.

https://stackoverflow.com/questions/291 ... g-mainloop

"""
What's wrong with update? There are several answers. First, it tends to complicate the code of the surrounding GUI. If you work the exercises in the Countdown program, you'll get a feel for how much easier it can be when each event is processed on its own callback. Second, it's a source of insidious bugs. The general problem is that executing [update] has nearly unconstrained side effects; on return from [update], a script can easily discover that the rug has been pulled out from under it. There's further discussion of this phenomenon over at Update considered harmful.
"""

Damit zu arbeiten kann also zu subtilen Fehlern fuehren, bis hin zu abstuerzen.

Wir haben hier und and 1000 anderen stellen gesagt, wie es geht. Das Problem von jks ist nix besonderes, das da ein anderes als die vorgestellten Loesungen verlangt - nur sein Verstaendnis ist halt nicht da.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und noch ein Nachtrag: ausser ein Fenster schon darzustellen, bevor der Mainloop betreten wurde, tut dein Programm nichts, was im Kontext hier hilfreicher waere, als der stinknormale Callback eines Buttons. Der ja schlussendlich eh der ausloesende Faktor sein wird.

Jakes Problem ist abstrakt das eines Fortschrittbalkens oder Spinners. Dazu braucht man aber after, und natuerlich einen Status, der abfragbar ist, und zB von einem Thread oder Prozess herruehrt.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi __deets__

Danke für deine Hinweise. Habe meine Informationen von:

Tkinter 8.5 reference: a GUI for Python
John W. Shipman
2013-12-31 17:59

Der schreibt Betreffs:

w.update()
This method forces the updating of the display. It should be used only if you know what you're
doing, since it can lead to unpredictable behavior or looping. It should never be called from an event
callback or a function that is called from an event callback.


w.update_idletasks()
Some tasks in updating the display, such as resizing and redrawing widgets, are called idle tasks
because they are usually deferred until the application has finished handling events and has gone
back to the main loop to wait for new events.
If you want to force the display to be updated before the application next idles, call the w.update_id-
letasks() method on any widget.


Dass die erste Variante mit Vorsicht anzuwenden ist aus seiner Beschreibung klar. Die zweite beschreibt er aber wesentlich weniger dramatisch. Scheinbar wurden diese Methoden kreiert um für bestimmte zeit verzögernde TCL Abläufe beschleunigen. Dachte 'jake-the-snake' möchte seine Messagebox mit der Meldung "Programm aktiv - Bitte warten..." anzeigen bevor seine Stundenlange Verschlüsselung erledigt ist, welche er aufruft bevor die 'root.mainloop()' Methode ausgeführt wir. Dies macht mein Skript aber genau. (Eventuell läuft dies unter Windows anders ab. -> Bei mir läuft Ubuntu 16.04)

Gruss wuf :wink:
Take it easy Mates!
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

@wuf in der Oberfläche (er hat eine Screenshot auf seiner Webseite) gehts klar um das verschlüsseln eines Textfeldes. Hat also nichts mit Anfang des Programms zu tun. Und das Update idletasks spart man sich, wenn man einfach per Button command ein Fenster aufmacht. Oder per After. Einen echten Mehrwert sehe ich da null in deinem Beispiel. Milde anders wäre das, wenn man eine echte Aufgabe erledigen würde, und zwischendurch updated. Nur ist das einer echten nebenläufigkeit unterlegen aus schon genannten Gründen .
jake-the-snake

Abend die Herren

So, nach viel Schweiß und Blut, welches transpiriert wurde, habe ich jetzt eine Lösung, die für meine Software 1.5 passt und in der nächsten Version 1.6 eingebaut wird. Das kann ich dann sowohl für das Verschlüsseln, wie auch für des Entschlüsseln nutzen. Aber zunächst bin ich froh, dass es läuft!

Ich habe das nun so gelöst, dass ich nach dem Klicken des roten Knopfes erst einmal ein Label öffne, mit dem Hinweis "Bitte warten..". Dieses Label lege ich in der finalen Version so geschickt über die Schaltelemente (kann man auch am unterem Beispiel sehen), dass man dort, für die Dauer der Label- Anzeige nicht klicken kann. Habe es ausprobiert - das geht tatsächlich. Danach springe ich nach der after- Methode in den Codierungs-Block und für die Dauer der Codierung bleibt die Anzeige "Bitte warten..." stehen. Am Ende der Codierung wird das Label entfernt. Und das Programm ist wieder betriebsbereit.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from tkinter import *

# Einleitung der App-Knoepfe / Hier gibt es jetzt nur einen zum Test
class App:
  
    def __init__(self, master):
        frame = Frame(master)
        frame.place(width=120, height=320, x=340, y=170)
        # Pre-Code-Button
        self.precoding = Button(frame, 
                         text="Verschlüsseln ►", fg="red", pady=5, padx=5,
                         command=self.write_precoding)
        self.precoding.pack()

####################
# Codierungs-Block #
####################

    def write_precoding(self):
        # Prozess-Meldung
        global fourLabel
        fourLabel = Label(root, text="Bitte warten...", font=("TimesNewRoman", 20), borderwidth=2, relief=("groove"), background=("#ff5a5a"), width=36, anchor=("center"))
        fourLabel.place(x=150,y=165)
        # Testausgabe Warte-Label
        print("Ansprung für Warte-Label OK...")
        root.after(1000, self.write_coding)

    def write_coding(self):
        # Testausgabe Beginn Code-Routine
        print("Beginn der Codierung OK...")
        i = 0
        while i <= 30000000:
            i = i + 1
        # Testausgabe Ende Code-Routine
        print("Ende der Codierung OK...")
        fourLabel.destroy()
        
####################
# Mainloop - Block #
####################

# Fenster-Titel
root = Tk(className=" Fenstername Blablabla")
root.resizable(FALSE,FALSE)
root.attributes("-topmost", 1)
root.wm_attributes('-type', 'splash')

# Knoepfe-App-Ende
app = App(root)

def center_window(width=300, height=200):
    # get screen width and height
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()

    # calculate position x and y coordinates
    x = (screen_width/2) - (width/2)
    y = (screen_height/2) - (height/2)
    root.geometry('%dx%d+%d+%d' % (width, height, x, y))
    
center_window(800, 480)

root.mainloop()
An Alle: Einen ganz herzlichen Dank für die Geduld und Ausdauer der hier Mitwirkenden. Auch einen lieben Dank an wuf, der hier gleich mehrfach größere Programme ablieferte. Ohne Eure Hilfe wäre ich nicht auf die eine, oder andere zündende Idee gekommen.
Und für wuf noch den Screenshot, den _deets_ erwähnt hat: https://www.crypto-code-tool.com/software.html.

So eine GUI ist halt doch was ganz anderes. Ich habe früher Frontend als Webinterface gebaut. Browsertechnisch ist man da doch recht schnell graphisch am Ziel. Der Datenaustausch erfolgte via .shtml-Seiten und serverseitigen Skripten via cgi. Kann man sich wie ein Ping-Pong Spiel vorstellen. Solche Anwendungen waren einfach auf Mehrplatzsysteme übertragbar. Ich habe da kleinere ERP's geschrieben. Mit Perl und SQL. Wenn ich sowas mit Python, bzw. Python ist gar nicht so das Problem - ich meine TKinter - umsetzen müsste... Ich bekäme keine Zwillinge, sondern eher Drillinge...

Gruss und Gute Nacht... bis die Tage...

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

@jake-the-snake: ich glaub ja kaum, dass bei den Programmierkünsten irgendwer bereit ist, Geld für ein BlackBox auszugeben. Verschlüsselung beruht darauf, dass der Algorithmus nachweisbar sicher ist. Asymmetrische Schlüssel mit 512bit (wenn das mit 512-facher Verschlüsselung gemeint ist), werden schon längst nicht mehr als sicher eingestuft. Also ohne Veröffentlichung des gesamten Source-Codes kauft niemand der bei Verstand ist, so ein Gerät.

Leider kann man ja jeden Tag lesen, wie viel Schrott produziert wird und es immer noch genug Dumme gibt, die den hohlen Versprechungen glauben.
Antworten