Python und TKinter (GUI)

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    bei mir hängt es bei der Umsetzung von einer "Zahlübergabe" in ein Eingabefeld.

    Also folgendes Ziel verfolge ich:

    Ich habe eine GUI gebaut wo ich in ein Eingbefeld ein Standardwert setzen möchte und den bei Drücken eines Buttons überschreiben möchte und wenn das geklappt hat diesen Wert übergeben.

    Ziel: Eine LED blinken lassen wobei der Eingabewert die Anzahl des Blinkens beschreibt. Bin soweit, dass wenn ich den Button start drücke die LED 5 mal blinkt. Nun möcht ich aber die Anzahl des Blinkens vom User bestimmen lassen. Es hakt aber schon daran dass ich kein Standardwert in das Eingabefeld übergeben kann bzw anschließend der Wert auch nicht übrgeben kann.
    Mein Ziel wäre es jetzt erstmal einen Standardwert in das Eingabefeld zu schreiben.
    Sorry bin Anfänger.


    Hier erstmal ein Code-Schnipsel:

    Wie gesagt habe iwie nicht die richtigen Befehe zur Hand und wäre für jeden Rat dankbar.

    Der Codeschnipsel selbst zeigt daher nur den GUI - Rahmen mit Textfeld und Eingabefeld.
    Habe mal rumprobiert aber alles war kein Ansatz der Lösung.
    Automatisch zusammengefügt:


    from Tkinter import *

    root = Tk()
    v = StringVar(root, value='2')
    e = Entry(root, textvariable=v)

    root.mainloop()

    Habe erstmal eine kleinen Lösungsansatz gefunden, denke aber dass StringVar ein String ist und ich den noch in ein Int überführen muss.
    Ich versuche es dann morgen nochmal.

    Trotzdem wäre ich für jeden weiteren Tip dankbar.

    Einmal editiert, zuletzt von luepues (20. September 2017 um 00:02)

  • Hi, danke habe ich mir dann heute auch mal bis einschließlich zu Eingabefeldern angesehen.

    Habe auch schon viel gelernt nur leider noch icht alles.

    Also habe das Eingabefeld mit einem Standardwert befüllen können und auch die Löschfunktion bei Übergabe habe ich schon angewendet.

    Mein Problem ist halt noch dass ich den "möglichen" Wert als String "einspeicher" und den natürlich nicht so verwenden kann. Kann mir vllt einer sagen, ob ich mit den verwendeten Befehlen die Umwandlung von String in Int hinbekomme und wenn ja wie?


    Wenn da einer ne kurze Lösung hat wäre ich sehr dankbar werde mich aber auch nochmal versuchen da weiter durchzukämpfen.

    mein Code würde jetzt in etwa so aussehen aber wie gesagt so klappt es nicht und die Beispiele in den Tutorials sind mir dann ohne Hilfe (noch) zu mächtig:


    Danke im voraus für jegliche Hilfe

  • Was du brauchst nennt sich Typecast (siehe hier).

    Wichtig ist aber dass du einen try-except-Block einbaust, falls dein String im Eingabefeld nicht in einen Integer umwandelbar ist.

    Code
    s = eingabe.get()
    try:
       i = int(s)
    except ValueError:
       i = 2 #Standartwert wenn s nicht konvertierbar
    print(i)

    Einmal editiert, zuletzt von Rasppineuling (22. September 2017 um 13:36)

  • hallo zusammen,

    habe es jetzt hinbekommen :bravo2: (iwie) :s . Mir fehlt es leider noch sehr viel an Python-Erfahrung. Den Code würde ich jetzt ungern posten da er wirklich laienhaft ist und ich mich jetzt erstmal noch eine zeitlang mit python beschäftigen muss.

    Das mit dem expect habe ich natürlich nicht in meinem Code, werde ich mir auch mal ansehen.


    Da es mir für den Anfang reicht, würde ich den Thread jetzt auf erledigt setzen, ABER ich werde bestimmt nochmal auf euch zurück kommen!!!

    An dieser Stelle nochmals :danke_ATDE:
    Automatisch zusammengefügt:

    Zitat von "Rasppineuling" pid='300788' dateline='1506069740'

    Wichtig ist aber dass du einen try-except-Block einbaust, falls dein String im Eingabefeld nicht in einen Integer umwandelbar ist.

    Code
    s = eingabe.get()
    try:
       i = int(s)
    except:
       i = 2 #Standartwert wenn s nicht konvertierbar
    print(i)

    Der größte Fehler meinerseits war glaube, dass ich mit dem Befehl print("%s" %(eingabe.get()) einen String erzeugt habe?!
    Und daher war das alles so schwierig - mit, wie du auch geschrieben hast: print(i), in deinem Fall, ging es dann recht zügig.


    :danke_ATDE: nochmals

    Einmal editiert, zuletzt von luepues (22. September 2017 um 11:53)

  • Hallo,

    Zitat

    Wichtig ist aber dass du einen try-except-Block einbaust, falls dein String im Eingabefeld nicht in einen Integer umwandelbar ist.


    Aber nicht wie gezeigt. Gaaaanz schlechter Stil und in 99,9% der Fälle n.i.O. Man möchte eigentlich nie ein nacktes `try...except`verwenden. Wenn fängt man bestimmte Fehler gezielt ab.

    Zitat

    Mir fehlt es leider noch sehr viel an Python-Erfahrung. Den Code würde ich jetzt ungern posten da er wirklich laienhaft ist


    Das ist IMHO die falsche Einstellung. Wenn du den Code hier postest und die Kritik umsetzt lernst du ziemlich sicher 10x schneller als mit jedem Buch, Tutorial etc.

    Gruß, noiseflloor

  • Zitat

    Mir fehlt es leider noch sehr viel an Python-Erfahrung. Den Code würde ich jetzt ungern posten da er wirklich laienhaft ist


    Das ist IMHO die falsche Einstellung. Wenn du den Code hier postest und die Kritik umsetzt lernst du ziemlich sicher 10x schneller als mit jedem Buch, Tutorial etc.

    Gruß, noiseflloor
    [/quote]

    Okay, leuchtet ein!!

    Code:


    Für jede nette Kritik und Korregierung bin ich dankbar!!!

  • "import *" ist ebenso böse wie die "try" Geschichte von oben :fies:
    Du weißt was du nutzt also importierst du entweder gezielt die Teile die du brauchst, oder "import tkinter" und setzt dann halt zB "tkinter.END"

    Benenne deine Variablen vernünftig, eindeutig ihrem Sinn und Zweck entsprechend.

    Setze Leerzeichen wo sie üblich sind, oder lass sie weg wo sie eher unnötig sind.
    Zum Beispiel "Label1= Label()" sieht komisch aus, lass entweder das Leerzeichen nach = weg oder setze auch davor ein Leerzeichen. Bei "eingabe = Entry()" hast du davor und dahinter eins gesetzt, bei den anderen aber nicht - murks, vermeide son Chaos, präferiere Einheitliche Struktur.

    Setze Kommas zum trennen von Parametern, keine Punkte.

    Vermeide Schreibfehler :fies: "Buton()" gibt es mit Sicherheit nicht.

    Setze Einheitlich Kommas. Mal setzt du nämlich plötzlich keine... Das gehört auch zum Stil bzw Einheitliche Struktur und so.

    Einheitliche Einrückungen. Pro Ebene nutzt man 4 Leerzeichen.
    Deine letzte Zeile zerstört die vorherige Ebene bzw macht diese quasi überflüssig.. Das '__main__' Krams wird nur ausgeführt wenn man das Script direkt ausführt, importiert mans aber anderswo würde in deinem Fall nur die letzte Zeile ausgeführt werden aber alle da drüber nicht und somit eine Fehlermeldung auswerfen....

    Das nochmalige setzen von int(anzblink) innerhalb des print's ist überflüssig. Durch "anzblink = 8" wäre es bereits vom Type int, und durch anzblink = int(blink) machst du es ebenfalls gezielt zum int.

    Anstatt "ValueError" kann man auch gezielt prüfen ob etwas ins Entry eingetragen wurde... Hier ein "try" Konstrukt zu nutzen ist also generell grenzwertig.

    Bei einer GUI wie Tkinter brauchst du keine zusätzliche while - das würde nämlich die GUI blockieren. Warum? Siehe FAQ => Nützliche Links / Linksammlung => python: Tkinter: Im Hintergrund zählen

  • Zitat von "meigrafd" pid='300867' dateline='1506110397'


    Anstatt "ValueError" kann man auch gezielt prüfen ob etwas ins Entry eingetragen wurde, indem man prüfen würde ob eingabe.get() None ist... Hier ein "try" Konstrukt zu nutzen ist also generell grenzwertig.

    Theoretisch kann aber auch einfach Quatsch im Entry stehen bspw. "sdfl" ==> Wäre nicht None, aber der Typecast würde trotzdem eine Exception werfen

  • Es bleibt dann trotzdem eine dirty und untypische Vorgehensweise :fies:

    Wenn man explizit nur Zahlen wünscht prüft man gezielt darauf, und wirft eine entsprechende Meldung aus - sonst weiß der Bediener nämlich nicht was er falsch gemacht hat.

    [code=php]
    if eingabe.get():
    if isinstance(eingabe.get(), int):
    anzblink = eingabe.get()
    else:
    print("Please enter a Number")
    return
    # do_something
    [/php]..normal nutzt man natürlich eine Meldung in der GUI, nicht in der Konsole ;)

    "fehlerhafter Code"

    [code=php]
    if eingabe.get() is not None:
    if isinstance(eingabe.get(), int):
    anzblink = eingabe.get()
    else:
    print("Please enter a Number")
    return
    # do_something
    [/php]

  • Zitat von "meigrafd" pid='300867' dateline='1506110397'


    "import *" ist ebenso böse wie die "try" Geschichte von oben :fies:
    Du weißt was du nutzt also importierst du entweder gezielt die Teile die du brauchst, oder "import tkinter" und setzt dann halt zB "tkinter.END"

    Bei dem ersten Punkt versteh ich direkt mal nicht warum import so böse ist, könntest du mir da eine geneuere Erläuterung geben?
    Was bedeutet tkinter.END? Verstehe ich leider nicht ohne Erläuterung - muss ich wohl mal noch Tutorials durchgehen.


    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Benenne deine Variablen vernünftig, eindeutig ihrem Sinn und Zweck entsprechend.

    eingabe ist für mich persönlich verständlich oder soll ich es eingabefeld nennen?
    anzblink ist für mich ebenfalls verständlich,
    callback1 habe ich in gpio_config geändert.


    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Setze Leerzeichen wo sie üblich sind, oder lass sie weg wo sie eher unnötig sind.
    Zum Beispiel "Label1= Label()" sieht komisch aus, lass entweder das Leerzeichen nach = weg oder setze auch davor ein Leerzeichen. Bei "eingabe = Entry()" hast du davor und dahinter eins gesetzt, bei den anderen aber nicht - murks, vermeide son Chaos, präferiere Einheitliche Struktur.

    Da ich den Code nicht auf dem Rechner schreibe, habe ich ihn abgetippt, im normalen Code ist es eingehalten. Durch Erläuterung kann ich es aber nachvollziehen.

    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Setze Kommas zum trennen von Parametern, keine Punkte.

    Könnte ich da ein Beispiel für bekommen, sehe in meinem Code keine Punkte zum trennen von Parametern...

    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Vermeide Schreibfehler :fies: "Buton()" gibt es mit Sicherheit nicht.

    Ich entschuldige, werde verstärkt drauf achten! Ich hoffe es ist verzeibar?!

    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Setze Einheitlich Kommas. Mal setzt du nämlich plötzlich keine... Das gehört auch zum Stil bzw Einheitliche Struktur und so.

    Könntest du mir da ein Beispiel nennen? Ohne Beispiel oder Erläuterung ist es für mich grade schwierig nachzuvollziehen.


    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Einheitliche Einrückungen. Pro Ebene nutzt man 4 Leerzeichen.
    Deine letzte Zeile zerstört die vorherige Ebene bzw macht diese quasi überflüssig.. Das '__main__' Krams wird nur ausgeführt wenn man das Script direkt ausführt, importiert mans aber anderswo würde in deinem Fall nur die letzte Zeile ausgeführt werden aber alle da drüber nicht und somit eine Fehlermeldung auswerfen....

    Was kann ich dagegen tun? Tutorials durcharbeiten oder evtl. einen Tip bekommen in welche Richtung es geht? Bin Anfänger, sorry dass ich es nicht gleich nachvollziehen kann ohne Erläuterung.

    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Das nochmalige setzen von int(anzblink) innerhalb des print's ist überflüssig. Durch "anzblink = 8" wäre es bereits vom Type int, und durch anzblink = int(blink) machst du es ebenfalls gezielt zum int.

    Danke, das verstehe ich auf Anhieb, da eine Erklärung bei ist und man es so sehr schnell nachvollziehen kann!

    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Anstatt "ValueError" kann man auch gezielt prüfen ob etwas ins Entry eingetragen wurde, indem man prüfen würde ob eingabe.get() None ist... Hier ein "try" Konstrukt zu nutzen ist also generell grenzwertig.


    Aufgrund der Aussage:
    Die Überprüfung ist so sinnfrei, denn ``eingabe.get()`` gibt niemals ``None`` zurück sondern höchstens einen leeren String.
    Muss ich mich als Anfänger noch intensiver mit beschäftigen, werde mal sehen wie weit ich da komme.


    Zitat von "meigrafd" pid='300867' dateline='1506110397'

    Bei einer GUI wie Tkinter brauchst du keine zusätzliche while - das würde nämlich die GUI blockieren. Warum? Siehe FAQ => Nützliche Links / Linksammlung => python: Tkinter: Im Hintergrund zählen


    Danke für den Link, da werd ich mich reinarbeiten.

    Also :danke_ATDE: für die Tipps.

    Einmal editiert, zuletzt von luepues (25. September 2017 um 19:17)

  • Zitat von "luepues" pid='301188' dateline='1506359406'

    Was bedeutet tkinter.END? Verstehe ich leider nicht ohne Erläuterung - muss ich wohl mal noch Tutorials durchgehen.

    Du machst " from tkinter import * ". Dadurch brauchst du im Script nicht mehr " tkinter.END " aufrufen sondern nur noch " END ". Und das wiederum führt dazu dass evtl. andere interne Namensbereiche die den selben Namen haben durch deine " from tkinter import * " Sache überschrieben werden könnten. Thats bad.
    Und ein weiter Nebeneffekt ist dass du jetzt gar nicht weißt was "tkinter.END" sein soll :fies: Schmeiß das Tutorial weg, das scheint nichts zu taugen.

    Zitat von "luepues" pid='301188' dateline='1506359406'

    eingabe ist für mich persönlich verständlich oder soll ich es eingabefeld nennen?
    anzblink ist für mich ebenfalls verständlich,
    callback1 habe ich in gpio_config geändert.

    Und was ist mit Label1, Label2 und b0? ;)

    Zitat von "luepues" pid='301188' dateline='1506359406'

    Da ich den Code nicht auf dem Rechner schreibe, habe ich ihn abgetippt, im normalen Code ist es eingehalten.

    Oha, das erklärt vllt einiges was ich bemängelt hatte... Übertrage deine Daten einfach dann brauchst du es nicht abtippen:
    FAQ => Nützliche Links / Linksammlung => Alternativen zu FTP/Samba (scp / lrzsz usw) (Übertragen von Dateien auf den Pi)

    Zitat von "luepues" pid='301188' dateline='1506359406'

    Könnte ich da ein Beispiel für bekommen, sehe in meinem Code keine Punkte zum trennen von Parametern...

    Keiner wusste vorher dass du den Code abgetippt hast - vermutlich hast du beim abtippen anstatt "," ein "." gedrückt:

    Code
    b0=Buton(root, text="start", bg="#FFFFFF". width=12, command=callback1)
    Zitat von "luepues" pid='301188' dateline='1506359406'

    Ich entschuldige, werde verstärkt drauf achten! Ich hoffe es ist verzeibar?!

    Nein :D

    Zitat von "luepues" pid='301188' dateline='1506359406'

    Was kann ich dagegen tun? Tutorials durcharbeiten oder evtl. einen Tip bekommen in welche Richtung es geht? Bin Anfänger, sorry dass ich es nicht gleich nachvollziehen kann ohne Erläuterung.

    Welchen Editor verwendest du zum programmieren?
    Ich nutze Notepad++, da kann man einstellen dass "Tabulatoren" durch 4 Leerzeichen ersetzt bzw genutzt werden... Möchte ich etwas einrücken drück ich die TAB Taste und erhalte 4 Leerzeichen, das ist dann eine Einrückungsebene.
    Es gibt auch gewisse Richtlinien an die man sich halten soll(te) damits einheitlich aussieht, die sog. PEP

  • Kurz klugscheissen zum letzten Satz:
    1) Bin ich froh, dass du auch noch auf den Zug aufgesprungen bist! :P
    2) PEP steht erstmal nur für Python Enhancement Proposal(s), eine Sammlung von Dokumenten und Ideen zum Verbessern der Sprache und Ausarbeitung neuer Features. Nur einige beschäftigen sich tatsächlich mit Styleguides, u. A. PEP 8 und 257, die wohl bekanntesten. Diese sind dafür um so wichtiger (nr. 8!) und ausführlich/stetig erweitert.

    Und ja, unter Pythonistas sind die PEPs quasi Gesetz und "considered best practice". Das tut Python auch gut, die C# Fraktion auf der Arbeit hat so etwas z. B. nicht und das merkt man auch wenn sie dann doch Python schreiben (müssen) :D
    Dem Rest deines Beitrags stimme ich ohne Ausnahme zu!

    LG

Jetzt mitmachen!

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