Seite 1 von 1
mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 12:31
von audacity363
Mahlzeit
Ich müsste ein komplettes Kartenspiel in einem Fenster anzeigen und diese müssen auch noch anklickbar sein. Also habe ich ein wenig gegoogelt und herausgefunden wie man Bilder auf einen Button bindet.
Bei einem funktioniert das auch noch ganze gut aber sobald ich einen zweiten hinzufüge wird der erste ausgeraut und ist auch nicht mehr anklickbar.
Habe euch mal eine Hardcopy hochgeladen damit ihr seht wie es aussieht:
http://www.directupload.net/file/d/3573 ... wa_png.htm
Der Code:
Code: Alles auswählen
from Tkinter import *
import Image, ImageTk
import tkMessageBox
def antwort():
tkMessageBox.showinfo("Test", "Button1")
def antwort1():
tkMessageBox.showinfo("Test", "Button2")
root = Tk()
root.title("Kartenspiel")
image = ImageTk.PhotoImage(Image.open("bilder/1_10.bmp"))
Button(root,image = image, command = antwort).grid(row=0, column=0)
image = ImageTk.PhotoImage(Image.open("bilder/1_11.bmp"))
Button(root,image = image, command = antwort1).grid(row=0, column=1)
root.mainloop()
Re: mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 12:36
von BlackJack
@audacity363: Du musst auf Python-Seite Referenzen auf die `PhotoImage`-Exemplare behalten, sonst werden die wieder freigegeben und Tk kann nicht mehr darauf zugreifen um sie anzuzeigen. Eine einfache Möglichkeit ist immer das Bild als Attribut an das Widget-Objekt zu binden auf dem es angezeigt wird. Aber in diesem Fall würde es sich anbieten die Kartenbilder vielleicht in eine Datenstruktur zu laden. Zum Beispiel eine Abbildung von der logischen Darstellung der Karten auf die `PhotoImage`-Exemplare.
Re: mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 13:18
von audacity363
Okey Danke hat funktioniert.
Gibt es eine Möglichkeit der Methode, die von dem Button aufgerufen wird, Parameter zu übergeben? Z.B. die ID des Buttons?
Re: mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 13:23
von EyDu
Schau dir dazu mal im Modul functools die Funktion partial an.
Re: mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 15:13
von audacity363
Na ja okey aber das bringt es nicht wirklich, da ich beim Parameter "command" ja gar keine Parameter übergeben kann.
Bei Java ist es ja z.B. Möglich einen ClickListner zu definieren und dort wird dann die ID des Buttons mitgegeben. Dementsprechend kann man dann abgleichen.
Re: mehrere Buttons mit Bildern
Verfasst: Mittwoch 26. März 2014, 15:25
von BlackJack
@audacity363: Doch das bringt es wirklich denn Du kannst damit Funktionen aus anderen Funktionen oder Methoden erstellen und angeben mit welchen Argumenten die aufgerufen werden sollen. Also genau das was Du haben wolltest.
Code: Alles auswählen
In [3]: def f(spam):
...: print spam
...:
In [4]: g = partial(f, 42)
In [5]: g()
42
Re: mehrere Buttons mit Bildern
Verfasst: Donnerstag 27. März 2014, 11:15
von audacity363
ja mir ist kla wie es funktioniert aber so müsste ich 52x das ganze "redefinen" und dann nochmal in der Funktion abfragen was denn jetzt übergeben wurde.
Erschwerend kommt noch dazu, dass ich die Buttons in zwei For Schleifen per .grid() verteile und dadurch immer die gleiche Funktion aufrufe. Daher die Frage ob man nicht einen "ClickListener" definieren kann bei dem die z.B. die ID des Buttons übergeben wird und die dann verglichen werden kann.
Re: mehrere Buttons mit Bildern
Verfasst: Donnerstag 27. März 2014, 11:32
von BlackJack
@audacity363: Was meinst Du mit 52 mal „redefinen”? Und wo musst Du was überprüfen? `f` ist in dem Beispiel der ”ClickListener” und `g` ist jetzt nur für das Beispiel. Das Ergebnis von `partial()` würde man direkt als `command`-Argument übergeben und nicht noch mal extra an einen Namen binden. Du willst doch eine Funktion ohne Argument die man als `command` übergeben kann, und die wenn man sie Aufruft, eine andere Funktion/Methode mit einem festen Wert/Id als Argument aufruft. Genau so etwas kannst Du mit `partial()` machen.
Re: mehrere Buttons mit Bildern
Verfasst: Donnerstag 27. März 2014, 11:59
von audacity363
OKey danke ich wusse nicht, dass man dies auch direkt dahinter schreiben kann. Nur bleibt immer noch das Problem, dass die Buttons keine eigene "ID" haben:
Code: Alles auswählen
def karten_suchen():
i = 0
for x in range(1,5):
for y in range(1, 15):
path = "bilder/" + str(x) + "_" + str(y) + ".bmp"
print path
try:
image[i] = ImageTk.PhotoImage(Image.open(path).resize((100, 150), Image.ANTIALIAS))
#image[i].resize((100, 150), Image.ANTIALIAS)
button[i] = Button(root,image = image[i], command = lambda: test(str(x), str(y)))
button[i].grid(row=x, column=y)
i += 1
except IOError:
print "Nicht gefunden"
Damit ich nicht alles einzeln schreiben muss mache ich es halt in einer Schleife. Als X und Y Wert nimmt er nun immer 4 und 14, was ja kla ist, da er ja erst nach dem Durchlauf darauf zugreift.
Re: mehrere Buttons mit Bildern
Verfasst: Donnerstag 27. März 2014, 12:17
von BlackJack
@audacity363: Natürlich kann man statt ``a = f(42); g(a)`` auch immer ``g(f(42))`` schreiben.
In Deinem Beispiel hast Du jetzt aber auch nicht `partial()` verwendet. Mach das mal, dann funktioniert das auch.
`image` und `button` sind eigenartig. Wo kommen die her und was sind denn da vorher für Werte drin? Oder sind das Wörterbücher statt Listen? Falls ja, warum? Die Werte stehen ausserdem für mehrere Bilder/Schaltflächen, das sollte man im Namen durch Mehrzahl ausdrücken, also `images` und `buttons`.
`root` kommt auch einfach so aus dem Nichts. Werte, ausser Konstanten, die man in Funktionen oder Methoden verwendet, sollten als Argumente übergeben werden. Funktionen sollten in sich geschlossene Aufgaben wahrnehmen und nicht über globale Datenstrukturen verwoben sein.
`i` sollte man nicht ”per Hand” hochzählen, sondern `enumerate()` verwenden.
Pfade setzt man besser mit `os.path.join()` zusammen und Werte und Zeichenketten mit der `format()`-Methode statt `str()` und ``+``.