tkinter bilder einfügen

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

    bin gerade was mit tkinter am versuchen.
    Allerdings stehe ich jetzt vor einem Problem welches ich als Neuling nicht selbst gelöst bekomme.
    Und die Lösungen die ich Mithilfe von Suchmaschinen finden konnte waren für mich unklar.
    Ich möchte meine Buttons gerne durch .gif oder .png Icons ersetzen und das so, das sie sich dem GPIO Status anpassen (ON / OFF).

    Meine aktuelle GUI sieht so aus:

    http://www.bilder-upload.eu/show.php?file=…-1502904649.jpg

    Noch nicht sehr ansehnlich aber funktioniert ;)

    Folgend kommt noch der Code

    http://paste.debian.net/981633/

    PS: Bin für jede Hilfe sehr dankbar! ;)

    Einmal editiert, zuletzt von wizard (16. August 2017 um 19:48)

  • from Tkinter import *

    sowas sollte man vermeiden. Du weißt was du nutzt also importiere gezielt was du nutzt, oder belasse es bei "import Tkinter" und später dann halt "Tkinter.Tk()" usw.
    Gewöhne dir auch direkt an sauber zu programmieren und mach nach einem " , " auch ein Leerzeichen, du aber machst es mal mit mal ohne... Dadurch wird es unübersichtlich.
    Als Einrückung nutzt man 4 Leerzeichen, keine TABs.

    Zu deinem Problem:
    [code=php]
    img = Tkinter.PhotoImage(file="an.gif")
    Tkinter.Button(root, image=img, text='AN', width=15, heigh=3, command=aus1, activebackground='white', fg='white', highlightbackground='white', background='green', font=("Courier", 30,)).grid(row=1, column=2)
    [/php]

    Das funktioniert aber nur mit GIF/PGM/PPM als Bildformat. Für andere musst du PIL verwenden:
    [code=php]
    from PIL import Image, ImageTk

    img = ImageTk.PhotoImage(Image.open("an.jpg"))
    Tkinter.Button(root, image=img, text='AN', width=15, heigh=3, command=aus1, activebackground='white', fg='white', highlightbackground='white', background='green', font=("Courier", 30,)).grid(row=1, column=2)
    [/php]

    Wichtig für beide:
    Nutze am besten absolute Pfade! FAQ => Nützliche Links / Linksammlung => pfade


    Als spätere Verbesserung rate ich dir zu nur einer einzigen Button Funktion der du dann nur den GPIO übergibst. Auch würde ich diese "anzeigen()" Orgie anders gestalten, du hast schon "after" entdeckt aber machst das nicht in nur einer Funktion.
    => http://paste.debian.net/hidden/983141f3/

  • Hey meigrafd

    Das mit dem Chaos ist mir bewusst bin Neuling und hab das aus verschiedenen Sachen mit trail and error zusammen gebastelt =D

    Ich danke dir aber sehr für deine Lösung und deine Hilfe trotz des Chaos ;)
    Automatisch zusammengefügt:
    Hey hab jetzt noch ein kleines Problem,

    ich hab mal deinen Code übernommen, es wird bei den "Einzel Steuerung Tasten" immer bloß die 4. geschaltet mit dem befehl alles an/aus funktioniert es jedoch.

    Was könnte das sein?
    PS: Bei den Buttons fehlte noch das tkinter. vor buttons.

    MFG

    Einmal editiert, zuletzt von wizard (16. August 2017 um 22:02)

  • Hm, warum lambda an der Stelle nicht funktionieren will weiß ich grad selber nicht, aber mit partial funktioniert es => http://paste.debian.net/981655/

  • Hey Forum, Hey meigrafd,

    ich bekomme das mit dem Bild als Button leider nicht hin mit meinen Fähigkeiten. Ich möchte Quasi die 8 Ein Aus Buttons durch 4 Buttons ersetzen die Quasi bloß ein wechselndes Bild (gif) darstellen sollen. Ein Bild , welches sich dem An oder Aus Statuts anpassen.
    Habe mir dazu ON OFF Symbole im netz organisiert die halt entweder grün oder rot "leuchten". Wenn die GPIO Stellung auf On steht sollte das grüne und bei off das rote angezeigt werden.

    Könntest du/Ihr mir vllt noch einmal helfen?

    Vielen Dank

    kevfei

  • Das Problem könnte das direkt angehängte .grid() sein:
    [code=php]
    Tkinter.Button(root, text='AN', width=15, heigh=3, command=partial(an, pin), activebackground='white', fg='white', highlightbackground='white', background='green', font=("Courier", 30,)).grid(row=index+1, column=2)
    [/php]

    Zum einen möchtest du ja das Bild entsprechend des Zustands ändern - also nur noch ein Button. Um das umzusetzen musst du das durch Tkinter.Button() erzeugte Objekt in eine Variable speichern um später darauf .config() anwenden zu können, und zum anderen muss man dann separat .grid() darauf anwenden sonst ist das Objekt ungültig - also so wie ichs mit "gpio_labels" gemacht habe.

    Mit nur wenigen Änderungen des Codes aus Beitrag#7 könnte das dann so aussehen => http://raspberrypi.roxxs.org/FILES/tkinter_button_img.mp4

    Bevor ich dir hierzu nun weiteren Code zeige möchte ich aber Eigeninitiative sehen

  • Hey meigrafd,

    Eigeninitiative war schön leider erfolglos =D

    ist das in der art gemeint?

    [code=php]def icon_button(master):
    for index, pin in enumerate(gpio_list):
    idx = index+1
    if GPIO.output(pin, 1):
    img = Tkinter.PhotoImage(file="button_on.gif").format(idx)
    gpio_button[pin].config(image=img_on, fg='green')
    else:
    ...........
    [/php]

    und der button

    [code=php]
    or index, pin in enumerate(gpio_list):
    Tkinter.Button(root, text='', width=15, heigh=3, command=partial(icon_button, pin), activebackground='white', fg='white', highlightbackground='white', background='green', font=("Courier", 30,)).grid(row=index+1, column=2)
    gpio_button[pin].grid(row=index+2, column=2)
    [/php]

  • Ja schon nicht schlecht aber leider nicht ganz richtig.

    Zum einen hab ich oben ja erwähnt das beim Tkinter.Button() Konstrukt nicht direkt .grid() angewendet werden kann/darf, zum anderen dass das durch Tkinter.Button() zurück gegebene Objekt in eine Variable gespeichert werden und darauf dann später .grid() angewendet werden soll - das hast du versäumt, also wie soll dann die 2. Zeile in der 'for' funktionieren?

    Das größte Problem mit deiner zusätzlichen Funktion ist dass du beim erzeugen des Buttons "command=partial(icon_button, pin)" gesetzt hast... Und nebenbei erwähnt: Wenn man schon Copy&Pasted dann bitte so das man es nicht bemerkt: master ? :-/ Du übergibst den Pin!
    ".format(idx)" ist aber auch falsch! Wo wird das deiner Meinung nach verwendet? Du hast dafür nirgends ein "{}" o.ä. stehen.

    Was würde nun passieren?
    Erst dann wenn ein Button von Dir betätigt wird, werden _alle_ Bilder neu gesetzt. Drückt man aber auf "ALLE AN" passiert mit deinen Bildern nichts.
    Das nächste Problem ist dass du jedes mal aufs neue Tkinter.PhotoImage() ausführst... Zum einen ist das nur ein mal nötig, zum anderen würde das in der Form verhältnismäßig extrem viel CPU und RAM beanspruchen. Und hier wäre auch wieder besagter absoluter Pfad angebracht.
    "fg" brauchst du da übrigens auch nicht weil wofür auch? forderground wird doch eh vom Bild überlagert.
    Viel wichtiger ist: Du brauchst bei jeder Änderung einen anderen "command", auch das kannst du über .config() ändern ;) So wie Du es nun geschrieben hast wird der GPIO auch nicht mehr geschaltet...

    Eine separate Funktion icon_button() brauchst du nicht. Wir haben doch bereits eine Funktion die automatisch alle 100ms unabhängig im Hintergrund ausgeführt wird und sich um den "anzeige"-Text, entsprechend des GPIO Zustands, kümmert.

    Also:
    Weniger Copy&Paste sondern lieber selber nachdenken - und ich sagte ja, mit nur wenigen Änderungen:
    - #BUTTON sieht später fast so aus wie #ANZEIGEN
    - "pfade" in Beitrag#4 beachten.
    -- pro Bilddatei nur ein mal Tkinter.PhotoImage() anwenden und zur richtigen Zeit, nachdem "root" erzeugt wurde, setzen.
    - in die vorhandene update_anzeige() das ändern des Button-Objekts einbauen.


    Sorry wenn das für dich gemein rüber kommt, aber man lernt nichts wenn man alles fertig vorgekaut kriegt. Ziel ist das Du es lernst und verstehst, denn dann kannst du selber laufen und brauchst nicht für jeden Schritt ne Stütze ;)

  • Hey meigrafd,

    gemein ist das nicht, ist nur schwierig jetzt einen überblick zu finden, wenn man den ersten teil schon aus mehreren Sachen kopiert hat ;) Ich hab eigentlich null Ahnung wenn es um sowas geht und leider auch wenig zeit um es zu lernen. Ich hab großen Respekt vor dir das du sowas kannst und auch so klasse beherrschst .

    Ich werde es dennoch die Tage mit deinen Tipps versuchen und hoffe das ich es hin bekomme.

    MFG kevfei

  • Hey ich kapituliere ich komme nicht dahinter und es ist mir ehrlich gesagt auch zu viel, da die ganzen Grundlagen fehlen.

    Dennoch danke für deine Zeit

  • Alt: http://paste.debian.net/981655/
    Neu: http://paste.debian.net/982051/

    Die wichtigsten Unterschiede:

    Alt:
    [code=php]
    #BUTTON
    for index, pin in enumerate(gpio_list):
    Tkinter.Button(root, text='AN', width=15, heigh=3, command=partial(an, pin), activebackground='white', fg='white', highlightbackground='white', background='green', font=("Courier", 30,)).grid(row=index+1, column=2)
    Tkinter.Button(root, text='AUS', width=15, heigh=3, command=partial(aus, pin), activebackground='white', fg='white', highlightbackground='white', background='red', font=("Courier", 30,)).grid(row=index+1, column=3)

    #anzeige
    def update_anzeige(master):
    for index, pin in enumerate(gpio_list):
    idx = index+1
    if GPIO.input(pin):
    txt = "{} - AN".format(idx)
    gpio_labels[pin].config(text=txt, fg='red')
    else:
    txt = "{} - AUS".format(idx)
    gpio_labels[pin].config(text=txt, fg='green')
    master.after(100, update_anzeige, master)
    [/php]

    Neu:
    [code=php]
    #BUTTON
    gpio_buttons=dict()
    for index, pin in enumerate(gpio_list):
    gpio_buttons[pin] = Tkinter.Button(root, image=btn_img_on, command=partial(an, pin))
    gpio_buttons[pin].grid(row=index+1, column=2)

    #anzeige
    def update_anzeige(master):
    for index, pin in enumerate(gpio_list):
    idx = index+1
    if GPIO.input(pin):
    txt = "{} - AN".format(idx)
    gpio_labels[pin].config(text=txt, fg='red')
    gpio_buttons[pin].config(image=btn_img_off, command=partial(aus, pin))
    else:
    txt = "{} - AUS".format(idx)
    gpio_labels[pin].config(text=txt, fg='green')
    gpio_buttons[pin].config(image=btn_img_on, command=partial(an, pin))
    master.after(200, update_anzeige, master)
    [/php]


    PS: Bitte nicht Beiträge vollständig quoten/zitieren, vor allem wenn diese genau da drüber stehen.

Jetzt mitmachen!

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