Seite 1 von 1

Bilder auf Button

Verfasst: Mittwoch 6. August 2014, 13:26
von AndiArbeit
Hallo liebes Python Forum,

ich habe bei einem Projekt ein kleines Problem. Ich habe eine Liste von Bildern (die Länge der liste ist unbekannt) und möchte diese Bilder auf Buttons darstellen.

Ein Teil meines Scripts sieht folgendermaßen aus.

Code: Alles auswählen

from PIL import Image, ImageTk
from Tkinter import *

def buttonmaker():
  reihe = 0
  spalte = 0

  bilder = [bild1, bild2, bild3, ... ]

  for bild in bilder :
    image = PhotoImage(file=bild)
    Button(root ,image =  image).grid(row = reihe, column = spalte)

    spalte += 1
    if spalte > 3 :
      spalte = 0
      reihe += 1

root = Tk()

buttonmaker()

mainloop() 
Das Problem ist, dass die Bilder nicht dargestellt werden. Das liegt wohl daran, dass Tkinter wahrscheinlich die Informationen der überschriebenen Images benötigt. Hat jemand eine Idee wie ich das lösen könnte ?

Vielen Dank im Vorraus
Gruß AndiArbeit

Re: Bilder auf Button

Verfasst: Mittwoch 6. August 2014, 13:30
von BlackJack
@AndiArbeit: Solange die Bilder angezeigt werden musst Du eine Referenz auf die Bildobjekte behalten. Also sie zum Beispiel in einer Liste speichern.

Re: Bilder auf Button

Verfasst: Mittwoch 6. August 2014, 13:37
von EyDu
Die for-Schleife geht noch ein wenig einfacher:

Code: Alles auswählen

for index, bild in enumerate(bilder):
    zeile, spalte = divmod(index, 3)

    ...

Re: Bilder auf Button

Verfasst: Mittwoch 6. August 2014, 13:55
von BlackJack
Ungetestet:

Code: Alles auswählen

import Tkinter as tk
from PIL import ImageTk


def create_image_buttons(master, image_paths, buttons_per_row=3):
    images = [ImageTk.PhotoImage(file=path) for path in image_paths]
    frame = tk.Frame(master)
    frame.images = images
    for i, image in enumerate(images):
        row, column = divmod(i, buttons_per_row)
        tk.Button(frame, image=image).grid(row=row, column=column)
    return frame


def main():
    image_paths = ['bild1', 'bild2', 'bild3']
    root = tk.Tk()
    frame = create_image_buttons(root, image_paths)
    frame.pack()
    root.mainloop()


if __name__ == '__main__':
    main()

Re: Bilder auf Button

Verfasst: Mittwoch 6. August 2014, 14:58
von Ene Uran
@EyDu, etwas besser ...
zeile, spalte = divmod(index, max_spalten)

Ach du lieber, schon gemacht, da mach ich den Putin verantwortlich!

Re: Bilder auf Button

Verfasst: Donnerstag 7. August 2014, 07:36
von AndiArbeit
Vielen Dank für die schnelle Hilfe.

Mein Script läuft leider immer noch nicht wie es soll. Bei den Bildern handelt es sich um jpg Dateien.
Im Grunde geht es im Script darum das ich mir aus der Schlagzeilenseite von Spiegel.de die Links und Titelbilder ziehe und dann die Bilder und Links auf die Buttons setzen will. Leider werden die jpgs nicht dargestellt.

Ich geh davon aus das ich das ich PIL nicht richtig verwende.

Für Korrekturen bin ich sehr Dankbar

Gruß AndiArbeit

Code: Alles auswählen

from PIL import Image, ImageTk
from Tkinter import *
 
def buttonmaker():
  reihe = 0
  spalte = 0
  counter = 0
  imageliste = []
 
  bilder = ["bild1.jpg", "bild2.jpg", "bild3.jpg", ... ]
 
  for bild in bilder :
    image = Image.open(bild)
    photo = ImageTk.PhotoImage(image)
    imageliste += [photo]
    Button(root ,image =  imageliste[counter]).grid(row = reihe, column = spalte)

    counter += 1 
    spalte += 1
    if spalte > 3 :
      spalte = 0
      reihe += 1
 
root = Tk()
 
buttonmaker()
 
mainloop() 

Re: Bilder auf Button

Verfasst: Donnerstag 7. August 2014, 08:41
von BlackJack
@AndiArbeit: Du musst dafür sorgen das solange die Bilder angezeigt werden, auch die Bildobjekte in Python existieren. Du sammelst die zwar (sehr umständlich) in `imageliste`, aber wenn die Funktion `buttonmaker()` zu ende ausgeführt wurde, verschwindet diese Liste und damit auch die Bildobjekte.

Re: Bilder auf Button

Verfasst: Donnerstag 7. August 2014, 08:54
von AndiArbeit
@ BlackJack Vielen Dank jetzt läuft es. Habe meine Liste als Globale Variable angegeben. Ich weiß das ist eine hässliche Methode aber es läuft :D. Nur für Lernzwecke wie hättest du Bildobjekte gesammelt ?

Re: Bilder auf Button

Verfasst: Donnerstag 7. August 2014, 08:56
von BlackJack
@AndiArbeit: Ich hatte da ja schon einen Beitrag mit Quelltext zu geschrieben.

Edit:

Code: Alles auswählen

import Tkinter as tk
from functools import partial
from io import BytesIO
from itertools import imap

import requests
from bs4 import BeautifulSoup
from PIL import Image, ImageTk

BASE_URL = 'http://www.spiegel.de'
TOP_HEADLINES_URL = BASE_URL + '/schlagzeilen/tops/index.html'


class ArticleButton(tk.Button):
    def __init__(self, master, url, headline, image, headline_label):
        image = ImageTk.PhotoImage(image)
        tk.Button.__init__(self, master, image=image, command=self._clicked)
        self.image = image
        self.url = url
        self.headline = headline
        self.headline_label = headline_label
        self.bind(
            '<Enter>', lambda _: headline_label.configure(text=self.headline)
        )
        self.bind('<Leave>', lambda _: headline_label.configure(text=''))

    def _clicked(self):
        print self.url


class ArticlesFrame(tk.Frame):
    def __init__(self, master, articles, articles_per_row=6):
        tk.Frame.__init__(self, master)
        headline_label = tk.Label(self)
        headline_label.pack()
        button_frame = tk.Frame(self)
        for i, (url, headline, image) in enumerate(articles):
            button = ArticleButton(
                button_frame, url, headline, image, headline_label
            )
            row, column = divmod(i, articles_per_row)
            button.grid(row=row, column=column)
        button_frame.pack()


def scrape_headline_link(base_url, link_node):
    return (
        base_url + link_node['href'],
        link_node['title'],
        Image.open(BytesIO(requests.get(link_node.img['src']).content))
    )


def scrape_headlines(base_url, headlines_url):
    return imap(
        partial(scrape_headline_link, base_url),
        BeautifulSoup(requests.get(headlines_url).text).select(
            'div.schlagzeilen-content div.article-image-box a'
        )
    )


def main():
    root = tk.Tk()
    articles_frame = ArticlesFrame(
        root, scrape_headlines(BASE_URL, TOP_HEADLINES_URL)
    )
    articles_frame.pack()
    root.mainloop()


if __name__ == '__main__':
    main()

Re: Bilder auf Button

Verfasst: Freitag 8. August 2014, 09:40
von jens
btw. damit das Bild nicht vom GC gelöscht wird, könnte man es auch an einem Button object packen, siehe Beispiel hier: http://tkinter.unpythonic.net/wiki/Phot ... PhotoImage