While-Schleife mit Button setzen/rücksetzen

  • Hallo zusammen,

    ich stehe momentan vor dem Problem, dass ich gerne mittels einer GUI über Tkinter mein Programm steuern möchte.
    Für das Programm möchte ich im Automatikbetrieb eine whileschleife starten, in welcher dann eine Regelung abläuft.
    Hierfür dachte ich mir ich setze mit dem Anklicken eines Buttons eine entsprechende Variable und frage diese dann in der while-schleife ab.
    Dies funktioniert jedoch nicht so wie gewünscht und auch andere Lösungsansätze sind schon gescheitert.. Hat jemand eine Lösung für solch ein Problem?

    Hier im Anhang mal der Grundgedanke meinerseits..

  • Vielen Dank schonmal für die Antwort! Für mich als relativen Leihen ist das jedoch ziemliches Kauderwelsch.. Auf was genau kommt es bei meinem Beispiel genau an?
    Heißt das, dass ich keine Eingaben mittels Button für die Logik machen sollte? Das wäre ziemlich schlecht :neutral:

    Einmal editiert, zuletzt von s0fralk (28. Mai 2017 um 15:43)

  • Was möchtest du wie starten?

    Man muss erstmal das Konzept einer GUI verstanden haben. Die GUI muss sich selbst darum kümmern alles im Fenster zu aktualisieren. Dies geschieht in einer Schleife. Wird nun eine Funktion aufgerufen, die das Programm blockiert, lässt sich die GUI solange nicht bedienen. Deswegen arbeitet man mit Threads um solche Funktionen auszulagern.

    Ich hab dein Code mal ein bisschen abgeändert, um zu demonstrieren was passieren kann und wie man das Problem umgeht.
    Getestet mit Python 3.6.

    Was du auf jeden Fall unbedingt nachlesen musst:


    Du wirst merken, dass es ab einem gewissen Punkt völlig Wahnsinnig ist alles in Funktionen auszulagern und die Referenz zum Objekt root mitzuschleppen. Dann hat man irgendwann Ravioli-Code.
    Es ist sinnvoll OOP für eine GUI zu nutzen. Dafür muss man aber erstmal das Konzept verstanden haben. Für so einfache Aufgaben, reicht aber auch Spagetti-Code. Man
    muss es sich selbst nicht komplizierter machen, als es schon ist.

    Noch ein Hinweis: Die Klassen von TKinter liefern alle eine Referenz zum erstellten Objekt zurück. D.h. der Aufruf tkinter.Button(root, text='foo') liefert ein Objekt zurück. Wenn du genau weißt, dass du diese Referenz später nicht benötigst, kannst du anstatt die Referenz einer Variable zuzuweisen, direkt die Methode pack() oder grid() verwenden. Das sähe dann so aus:

    Code
    Button(root, text="Einrichten", bg="#FFFF00", width=20, command=partial(handle_man, root)).grid(row=0, column=0, padx=10, pady=3)

    Sieht aber ziemlich hässlich aus und hat mit dem eigentlichen Problem nichts zu tun.

    Hat eigentlich schonmal jemand ein Dict genutzt, um die Eigenschaften an Button usw. zu übergeben? Fällt mir gerade so auf.

    Code
    btn_man_prop = dict(bg='#FFFF00', width=20, command=partial(handle_man, root))
    grid_man = dict(row=0, column=0, padx=10, pady=3)
    Button(**btn_man_prop).grid(**grid_man)

    Was mir noch aufgefallen ist:


    • Einrückung immer mit 4 Leerzeichen, keine Tabulatoren und auch nicht nur 2 Leerzeichen
    • Code auf Modulebene in Funktionen und Klassen auslagern.
    • Code in logische verständliche Funktionen aufteilen
    • Objekte nutzen, wenn man einen Status benötigt. (z.B. die Referenz zum root Objekt)
    • Aussagekräftige Variablen nutzen: Adjektive/Nomen für Variablen, Verben für Funktionen und Nomen für Klassen.
    • Plural für Sequenzen (list, tuple, set, ...), Singular für atomare Objekte (float, int, str, bool)

      Code
      a = ['Zucker', 'Milch', 'Eier', 'Mehl', 'Backpulver']
      for x in a:
          print(x)
      
      
      zutaten = ['Zucker', 'Milch', 'Eier', 'Mehl', 'Backpulver']
      for zutat in zutaten:
          print(zutat)


    Du kannst übrigens auch UTF8 für Variablen, Funktionen und Klassen verwenden:

    Da wir aber International arbeiten, sollte jedes Programm in englisch gehalten sein.

  • Hi, danke für die ausführliche Antwort. Leider habe ich nur noch bis 19. Juni Zeit mein Programm zu realisieren und bis dahin werde ich wohl mit all der Lektüre plus Verständnis nicht durch sein.. Ich werde einfach versuchen mir etwas "quick and dirty" zusammenzuklicken..

    Im Detail um was es gehen soll:

    Ich möchte zu Beginn eine Auswahl treffen können ob Automatikbetrieb oder Handbetrieb.
    -> Entscheidet man sich für Handbetrieb: Neue Oberfläche öffnet sich und vier Buttons erscheinen : Heben, Senken, Motor Ein, Motor Aus + Homebutton
    -> Entscheidet man sich für Automatikbetrieb: Neue Oberfläche bietet vier Buttons an: Variante 1 wählen, Variante 2 wählen, Start, Stop + Homebutton

    Im Automatikbetrieb soll dann eine einfache Höhenregelung starten.
    Im Handbetrieb soll manuell auf und abgefahren werden, so lange man den Button gedrückt hält.


    Ich überlege gerade ob eine Auswahl mit Radiobuttons derartiges Unterfangen einfacher macht. Zudem ziehe ich immer mehr in Betracht alle Elemente auf einer Ebene darzustellen.

    Einmal editiert, zuletzt von s0fralk (28. Mai 2017 um 19:00)

  • Hallo,

    Zitat

    Für mich als relativen Leihen ist das jedoch ziemliches Kauderwelsch.. Auf was genau kommt es bei meinem Beispiel genau an?


    Wenn du (Python-) Laie bist, dann willst du keine GUI programmieren. Um das selber umsetzen zu können ist zumindest ein leises Verständnis von der Instanzierung von Klassen und Methodenaufrufen notwendig Sonst kannst du nicht wirklich verstehen, was du da treibst.

    Was bei dir noch dazu kommt ist, dass du ggf. Nebenläufigkeit brauchst und zwei (oder mehr?) Threads / Prozesse, die miteinander kommunizieren. Geht (ohne Probleme), ist für einen Anfänger aber auch alles andere als trivial.

    _Musst_ du eine GUI programmieren oder willst du das? Im gegebenen Fall ist es sowieso ggf. einfacher, erst eine funktionierendes Programm für die Kommandozeile zu schreiben und dann ggf. noch die GUI zu machen.

    Gruß, noisefloor

  • Brauche zwingend eine GUI. Und ja Python ist schon nicht ohne.. ich dachte es ist einigermaßen vergleichbar mit c# oder vba, aber da habe ich mich wohl getäuscht.. Auch functions und methoden im rahmen von c# sind mir nicht unbekannt, aber dass ich einen simplen zustand eines buttons nicht abfragen kann, geht mir nicht in den kopf


  • ich stehe momentan vor dem Problem, dass ich gerne mittels einer GUI über Tkinter mein Programm steuern möchte.
    Für das Programm möchte ich im Automatikbetrieb eine whileschleife starten, in welcher dann eine Regelung abläuft.
    Hierfür dachte ich mir ich setze mit dem Anklicken eines Buttons eine entsprechende Variable und frage diese dann in der while-schleife ab.

    Bei Tkinter gibts besondere Umstände, was viele gar nicht bedenken: Es läuft bereits eine while Schleife: mainloop
    Durch den mainloop wird "after" kontinuierlich überprüft, bei jedem Schleifendurchlauf wird also geprüft ob es an der Zeit ist "after" auszuführen. Mit der Zeitangabe (in millisekunden) legt man fest nach wie viel Zeit die in der after Methode festgelegte Funktion ausgeführt werden soll.
    Und genau das kann man hier ausnutzen.

    Siehe dazu:
    FAQ => Nützliche Links / Linksammlung => python: Tkinter: Im Hintergrund zählen
    FAQ => Nützliche Links / Linksammlung => python: TKinter Zähler
    https://github.com/meigrafd/Sampl…kinter/after.py
    https://github.com/meigrafd/Sampl…kinter_Count.py


  • aber dass ich einen simplen zustand eines buttons nicht abfragen kann, geht mir nicht in den kopf

    Doch kannst du. Steht in dem Beispiel was meigrafd gepostet hat: https://github.com/meigrafd/Sampl…kinter/after.py die Methode startstop_func erledigt die Aufgabe.
    Du hast den callback und der callback setzt dann eine Variable auf True, wenn sie False war und umgekehrt. Der Text des Buttons wird durch startstop_button["text"] = 'Foo' zugewiesen.

    Einmal editiert, zuletzt von RestlessMud46765 (29. Mai 2017 um 02:06)

  • Hallo,

    Zitat

    aber dass ich einen simplen zustand eines buttons nicht abfragen kann, geht mir nicht in den kopf


    Denkfehler: Ein Button ist eine Schaltfläche, die einem Taster entspricht und _nicht_ einem Schalter. D.h. es gibt keinen an/aus Zustand ootb, sondern nur "gedrückt" und "nicht gedrückt". Auf das Drücken kannst du reagieren, siehe Post von DeaD_EyE.

    Zitat

    ich dachte es ist einigermaßen vergleichbar mit c# oder vba, aber da habe ich mich wohl getäuscht..


    Sagen wir mal so: falsche Einstellung. Wenn du eine anderen Programmiersprache nutzen möchtest, solltest du dich auf deren Konzepte und Idiome einlassen. Sonst wir es schwierig. Im gegebenen kommt vielleicht noch dazu, dass das Erstellen von (einfachen) GUIs mit C# oder VBA durch deren enge Bindung an Windows und dessen GUI-Framework evtl. einfacher ist.

    Gruß, noisefloor

  • Vielen vielen Dank für die vielen Antworten!
    Die Sache mit dem after könnte funktionieren. habe mir den code intensiv angeschaut und einigermaßen verstanden. Umsetzung erfolgt dann hoffentlich demnächst.

Jetzt mitmachen!

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