Tkinter filedialog Bild einfügen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JGS-Coder
User
Beiträge: 8
Registriert: Donnerstag 19. November 2020, 08:26

Hey Leute,
ich sitze gerade an einem kleinen Projekt in Tkinter und ich habe ein Problem mit dem einfügen von Bildern. Ich möchte, dass der Benutzer über filedialog ein Bild auswählen kann und dieses dann in der größe angepasst und in das Text Widget eingefügt wird.

Hier ein Ausschnitt von meinem Code:

Code: Alles auswählen

from tkinter import Tk, Text, INSERT, PhotoImage, filedialog, Scrollbar, Menu

root = Tk()
root.geometry("700x400")

# Funktionen
def InsertIMG():
    IMGfile = filedialog.askopenfiles(filetypes=[('Bilder', '.png')])
    my_image = PhotoImage(file=IMGfile)
    position = EingabeFeld.index(INSERT)
    EingabeFeld.image_create(position, image=my_image)

# Eingabefeld
EingabeFeld = Text(root,font=("Calibri",12), width=60, height=15)
EingabeFeld.place(x=135, y=50)
scroll_y = Scrollbar(root, orient="vertical", command=EingabeFeld.yview)
scroll_y.place(x=617, y=51, height=288)
EingabeFeld.configure(yscrollcommand=scroll_y.set)

# Menü
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="Foto einfügen", menu=filemenu)
filemenu.add_command(label="Foto auswählen", command=InsertIMG)

root.mainloop()
Vielen Dank im voraus für die Hilfe :D
Die Idee ist nicht alles.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo JGS-Coder,
benutze askopenfilename, dies gibt dir den Pfad zum Bild zurück.
Askopenfile will das File zum Lesen öffnen.
Dann kann meines Wissens die Klasse Pfhotoimage nur .gif, .pgm, oder .ppm Bilder einbinden.
Und das auch nur auf Labels, Text, Canvases oder Buttons.
Gruss
Peter
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@JGS-Coder: hilfreich wäre es, wenn Du auch noch die Fehlermeldung, die erscheint, hier posten würdest, denn da steht alles drin, was man wissen muß, um den Fehler zu beheben.
Da siehst Du, dass Du versuchst ein Textfileobjekt dort zu verwenden, wo ein Dateiname erwartet wird.
Wenn Du dann in die Dokumentation schaust, wirst Du dort lesen dass askopenfiles ein Fileobjekt liefert, askopenfilename dagegen den Dateiname, was Du ja eigentlich willst. Damit Tkinter das Bild auch darstellen kann, muß man das PhotoImage-Objekt im Speicher behalten.

Variablennamen werden in Python komplett klein geschrieben. So Anhängsel, wie my, die nichts zum Verständnis beitragen, weglassen.
Alles was eine Funktion braucht, muß sie über ihre Argumente bekommen.
place sollte man nicht verwenden, statt dessen benutzt man grid oder pack.

Code: Alles auswählen

import tkinter as tk
from tkinter.filedialog import askopenfilename
from functools import partial

# Funktionen
def insert_image(eingabe_feld):
    filename = askopenfilename(filetypes=[('Bilder', '.png')])
    image = tk.PhotoImage(file=filename)
    eingabe_feld.images.append(image)
    position = eingabe_feld.index(tk.INSERT)
    eingabe_feld.image_create(position, image=image)

def main():
    root = tk.Tk()
    root.geometry("700x400")

    # Eingabefeld
    eingabe_feld = tk.Text(root, font=("Calibri",12))
    eingabe_feld.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
    scroll_y = tk.Scrollbar(root, orient="vertical", command=eingabe_feld.yview)
    scroll_y.pack(side=tk.LEFT, fill=tk.Y)
    eingabe_feld.configure(yscrollcommand=scroll_y.set)
    eingabe_feld.images = []

    # Menü
    menu = tk.Menu(root)
    root.config(menu=menu)
    filemenu = tk.Menu(menu)
    menu.add_cascade(label="Foto einfügen", menu=filemenu)
    filemenu.add_command(label="Foto auswählen", command=partial(insert_image, eingabe_feld))
    root.mainloop()

if __name__ == '__main__':
    main()
JGS-Coder
User
Beiträge: 8
Registriert: Donnerstag 19. November 2020, 08:26

Sirius3 hat geschrieben: Donnerstag 19. November 2020, 14:50 @JGS-Coder: hilfreich wäre es, wenn Du auch noch die Fehlermeldung, die erscheint, hier posten würdest, denn da steht alles drin, was man wissen muß, um den Fehler zu beheben.
Da siehst Du, dass Du versuchst ein Textfileobjekt dort zu verwenden, wo ein Dateiname erwartet wird.
Wenn Du dann in die Dokumentation schaust, wirst Du dort lesen dass askopenfiles ein Fileobjekt liefert, askopenfilename dagegen den Dateiname, was Du ja eigentlich willst. Damit Tkinter das Bild auch darstellen kann, muß man das PhotoImage-Objekt im Speicher behalten.

Variablennamen werden in Python komplett klein geschrieben. So Anhängsel, wie my, die nichts zum Verständnis beitragen, weglassen.
Alles was eine Funktion braucht, muß sie über ihre Argumente bekommen.
place sollte man nicht verwenden, statt dessen benutzt man grid oder pack.

Code: Alles auswählen

import tkinter as tk
from tkinter.filedialog import askopenfilename
from functools import partial

# Funktionen
def insert_image(eingabe_feld):
    filename = askopenfilename(filetypes=[('Bilder', '.png')])
    image = tk.PhotoImage(file=filename)
    eingabe_feld.images.append(image)
    position = eingabe_feld.index(tk.INSERT)
    eingabe_feld.image_create(position, image=image)

def main():
    root = tk.Tk()
    root.geometry("700x400")

    # Eingabefeld
    eingabe_feld = tk.Text(root, font=("Calibri",12))
    eingabe_feld.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
    scroll_y = tk.Scrollbar(root, orient="vertical", command=eingabe_feld.yview)
    scroll_y.pack(side=tk.LEFT, fill=tk.Y)
    eingabe_feld.configure(yscrollcommand=scroll_y.set)
    eingabe_feld.images = []

    # Menü
    menu = tk.Menu(root)
    root.config(menu=menu)
    filemenu = tk.Menu(menu)
    menu.add_cascade(label="Foto einfügen", menu=filemenu)
    filemenu.add_command(label="Foto auswählen", command=partial(insert_image, eingabe_feld))
    root.mainloop()

if __name__ == '__main__':
    main()
Der Code hat funktioniert, vielen Dank. Und natürlich auch danke auch für die Ratschläge. :D
Die Idee ist nicht alles.
JGS-Coder
User
Beiträge: 8
Registriert: Donnerstag 19. November 2020, 08:26

Und kann ich auch irgendwie die Größe des Bildes anpassen? Wenn ich '.resize' benutze bekomme ich folgenden Fehler:

Code: Alles auswählen

AttributeError: 'PhotoImage' object has no attribute 'resize'
Wie kann ich das beheben? Danke im vorraus. :mrgreen:
Die Idee ist nicht alles.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dazu musst du Pillow benutzen. Das integriert sich mit tkinter. Und kann Bildoperationen.
JGS-Coder
User
Beiträge: 8
Registriert: Donnerstag 19. November 2020, 08:26

__deets__ hat geschrieben: Freitag 20. November 2020, 11:09 Dazu musst du Pillow benutzen. Das integriert sich mit tkinter. Und kann Bildoperationen.
Und welchen Funktion muss ich dafür nutzen?

Außerdem ist mir aufgefallen, dass ich die Bilder nicht speichern kann. Alles was man schreibt soll am Ende in einer .txt Datei gespeichert werden. Allerdings wird das Bild nicht gespeichert. Sobald man die datei öffnet findet man nur das geschriebene, von dem Bild ist keine Spur.
Die Idee ist nicht alles.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@JGS-Coder: Wie kommst du denn darauf, dass "PhotoImage" eine Methode names "resize" hat? Wo in der Dokumentation hast du das gefunden?

Soweit ich weiß, musst du das Bild mit Pillow laden, dann entsprechend modifizieren und das Resultat sind dann die Daten für das PhotoImage.

Da hier niemand weiß, wie du speicherst und was du vor hast, kann dir deine letzte Frage niemand beantworten. Das txt steht übrigen für "Text" - nicht für "Text und Bilder". Also für den Fall, dass du davon ausgehst, dass das Bild dann in der Datei einfach angezeigt wird: Das geht nicht.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du mal probiert Pillow und tkinter zusammen zu recherchieren? Was konkret an den gefundenen Beispielen ist dir nicht klar?
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Bilder sind in einem Text-Feld nur Referenzen auf die Bildobjekte, das sieht man schön am Dump `eingabe_feld.dump("1.0","end")`. Die Bilder mußt Du selbst referenzieren und in einer geeigneten Form speichern.
Antworten