Problem mit tkinter.PhotoImage

Fragen zu Tkinter.
Antworten
DerBotaniker
User
Beiträge: 5
Registriert: Donnerstag 11. Mai 2023, 17:40

Liebe alle,

ich bin in letzter Zeit damit beschäftigt, mich in tkinter einzuarbeiten und stoße dabei aber auf das Problem, dass ich bei hoffentlich richtiger Übernahme des Codes aus dem Python 3 Handbuch von Ernesti und Kaiser (6. Aufl., S. 862) trotzdem das Programm nicht starten kann. Nach einer Weile habe ich herausgefunden, dass es ausschließlich an den Zeilen 8 und 9 liegt. Es spielt keine Rolle, wie komplex ich den Datei-Pfad gestalte. Es scheint so, als könnte Python mit den Befehlen nicht umgehen...

import tkinter
class MyApp(tkinter.Frame):
def __init__(self, master):
super().__init__(master)
self.pack()
self.cv=tkinter.Canvas(self, width=800, height=600)
self.cv.pack()
self.img = tkinter.PhotoImage(file="Python.png")
self.cv.create_image(0, 0, image=self.img, anchor="nw")


root = tkinter.Tk()
app = MyApp(root)
app.mainloop()
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

ich versuche gerade herauszufinden, was du für Probleme mit dem Code hast. Wenn ich den, mit einem beliebigen *.png - Bild, laufen lasse, dann erhalte ich keine Fehlermeldung und das Bild wird angezeigt.

Was bekommst du denn für eine (vollständige) Fehlermeldung? Oder was ist nicht so, wie du es gerne hättest?

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte Code in den dafür vorgesehenen Code Tags posten, damit die in Python relevanten Einrückungen erhalten bleiben.

Zu deinem Problem: es wird trotzdem ein Pfad-Problem sein. Mit

Code: Alles auswählen

import pathlib

PATH = “Bild.png”

assert pathlib.Path(PATH).exists()
muss durchlaufen. Vorher kann PhotoImage nicht Hexen.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

tkinter wird üblicherweise als tk abgekürzt. Ein Frame sollte sich nicht selbst im übergeordneten Widget platzieren. Es sollte eine main-Funktion geben. Variablennamen sollte man nicht abkürzen.
Ein My-Präfix ist sinnlos, weil es keinen Mehrwert bietet, kann also weg. Tkinter definiert einige Konstanten, die man nutzen sollte.

Du gibst den Pfad zum Bild relativ zum aktuellen Arbeitsverzeichnis an. Wahrscheinlich ist es nicht das Verzeichnis, in dem das Bild liegt. Üblicherweise gibt man Pfade, die hart im Code stehen, relativ zur Python-Datei an, und legt diese Dateien auch dann passend dazu ab.

Code: Alles auswählen

import tkinter as tk
from pathlib import Path

class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.canvas = tk.Canvas(self, width=800, height=600)
        self.canvas .pack()
        self.image = tk.PhotoImage(file=Path(__file__).parent / "Python.png")
        self.canvas .create_image(0, 0, image=self.image, anchor=tk.NW)

def main():
    root = tk.Tk()
    app = App(root)
    app.pack()
    app.mainloop()

if __name__ == "__main__":
    main()
NinoBaumann
User
Beiträge: 72
Registriert: Samstag 25. April 2020, 19:03

Sirius3 hat geschrieben: Freitag 12. Mai 2023, 08:23 tkinter wird üblicherweise als tk abgekürzt. Ein Frame sollte sich nicht selbst im übergeordneten Widget platzieren. Es sollte eine main-Funktion geben. Variablennamen sollte man nicht abkürzen.
Ein My-Präfix ist sinnlos, weil es keinen Mehrwert bietet, kann also weg. Tkinter definiert einige Konstanten, die man nutzen sollte.

Du gibst den Pfad zum Bild relativ zum aktuellen Arbeitsverzeichnis an. Wahrscheinlich ist es nicht das Verzeichnis, in dem das Bild liegt. Üblicherweise gibt man Pfade, die hart im Code stehen, relativ zur Python-Datei an, und legt diese Dateien auch dann passend dazu ab.

Code: Alles auswählen

import tkinter as tk
from pathlib import Path

class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.canvas = tk.Canvas(self, width=800, height=600)
        self.canvas .pack()
        self.image = tk.PhotoImage(file=Path(__file__).parent / "Python.png")
        self.canvas .create_image(0, 0, image=self.image, anchor=tk.NW)

def main():
    root = tk.Tk()
    app = App(root)
    app.pack()
    app.mainloop()

if __name__ == "__main__":
    main()
Hallo Sirus3,

wenn ich den Code anwende wird nur ein Ausschnitt des Bildes dargestellt. Wieso wird das Bild nicht auf die im Code angegebene Größe skaliert?

VG
Nino
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Warum denkst du das sollte passieren?
NinoBaumann
User
Beiträge: 72
Registriert: Samstag 25. April 2020, 19:03

__deets__ hat geschrieben: Freitag 12. Mai 2023, 13:46 Warum denkst du das sollte passieren?
Weil ich es mit einem Bild getestet habe. Wenn ich die Größe ändere sehe ich mehr vom Bild. Demnach muss es in irgendeiner Weise einen Ausschnitt zeigen.
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@NinoBaumann: Das beantwortet nicht wirklich die Frage warum Du denkst es sollte auf den sichtbaren Bereich skaliert werden. Wird es halt nicht. Würde es das, müsste es ja auch einen dokumentierten Weg geben das *nicht* zu skalieren, wenn man das nicht haben will.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DerBotaniker
User
Beiträge: 5
Registriert: Donnerstag 11. Mai 2023, 17:40

Sirius3 hat geschrieben: Freitag 12. Mai 2023, 08:23 tkinter wird üblicherweise als tk abgekürzt. Ein Frame sollte sich nicht selbst im übergeordneten Widget platzieren. Es sollte eine main-Funktion geben. Variablennamen sollte man nicht abkürzen.
Ein My-Präfix ist sinnlos, weil es keinen Mehrwert bietet, kann also weg. Tkinter definiert einige Konstanten, die man nutzen sollte.

Du gibst den Pfad zum Bild relativ zum aktuellen Arbeitsverzeichnis an. Wahrscheinlich ist es nicht das Verzeichnis, in dem das Bild liegt. Üblicherweise gibt man Pfade, die hart im Code stehen, relativ zur Python-Datei an, und legt diese Dateien auch dann passend dazu ab.

Code: Alles auswählen

import tkinter as tk
from pathlib import Path

class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.canvas = tk.Canvas(self, width=800, height=600)
        self.canvas .pack()
        self.image = tk.PhotoImage(file=Path(__file__).parent / "Python.png")
        self.canvas .create_image(0, 0, image=self.image, anchor=tk.NW)

def main():
    root = tk.Tk()
    app = App(root)
    app.pack()
    app.mainloop()

if __name__ == "__main__":
    main()
Das funktioniert. Vielen Dank dafür!

Um nun das Bild auf die Größe des Canvas zu reduzieren, müsste ich die resize-Option von pillow nutzen. Ich habe im Folgenden einen Code eingefügt, der genau das machen soll. Bloß werde ich mal wieder damit gestraft, dass sich mein Programm damit nicht öffnen lässt...

Code: Alles auswählen

import tkinter as tk
from PIL import Image, ImageTk 
from pathlib import Path

class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        self.canvas = tk.Canvas(self, width=800, height=800)
        self.canvas.pack()
        self.bild = Image.open(file=Path(r"C:\Users\xyz\Downloads\Python.png").parent/"Python.png")
        self.bild_verändert= self.bild.resize(width=800, height=800, Image.ANTIALIAS)
        self.bild_neu= ImageTk.PhotoImage(self.bild_verändert)
        self.canvas.create_image(0, 0, anchor="nw", image=self.bild_neu)


def main():
    root = tk.Tk()
    app = App(root)
    app.pack()
    app.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
Axel-WAK
User
Beiträge: 62
Registriert: Dienstag 29. November 2022, 11:52

Geht es so?

Code: Alles auswählen

        self.bild = Image.open(r"C:\Users\xyz\Downloads\Python.png")
        self.bild_verändert= self.bild.resize([800, 800], Image.ANTIALIAS)
OS: LMDE5 *** Homepage *** Github Seite
DerBotaniker
User
Beiträge: 5
Registriert: Donnerstag 11. Mai 2023, 17:40

Axel-WAK hat geschrieben: Freitag 12. Mai 2023, 19:05 Geht es so?

Code: Alles auswählen

        self.bild = Image.open(r"C:\Users\xyz\Downloads\Python.png")
        self.bild_verändert= self.bild.resize([800, 800], Image.ANTIALIAS)
Leider auch nicht.
Benutzeravatar
Axel-WAK
User
Beiträge: 62
Registriert: Dienstag 29. November 2022, 11:52

Fehlermeldungen wären vielleicht hifreich.

Gibt es die Datei C:\Users\xyz\Downloads\Python.png überhaupt.

Bei mir funktioniert das mit einer existierenden Datei.
OS: LMDE5 *** Homepage *** Github Seite
DerBotaniker
User
Beiträge: 5
Registriert: Donnerstag 11. Mai 2023, 17:40

Es war immer noch ein Pfadproblem, das ich aber schlussendlich lösen konnte. Vielen Dank für die hilfreichen Ratschläge!
NinoBaumann
User
Beiträge: 72
Registriert: Samstag 25. April 2020, 19:03

DerBotaniker hat geschrieben: Montag 15. Mai 2023, 07:32 Es war immer noch ein Pfadproblem, das ich aber schlussendlich lösen konnte. Vielen Dank für die hilfreichen Ratschläge!
Wenn man eine Lösung findet dann schreibt man diese auch normalerweise in den Beitrag rein damit andere mit demselben Problem eine Lösung haben.
DerBotaniker
User
Beiträge: 5
Registriert: Donnerstag 11. Mai 2023, 17:40

NinoBaumann hat geschrieben: Montag 15. Mai 2023, 13:39
DerBotaniker hat geschrieben: Montag 15. Mai 2023, 07:32 Es war immer noch ein Pfadproblem, das ich aber schlussendlich lösen konnte. Vielen Dank für die hilfreichen Ratschläge!
Wenn man eine Lösung findet dann schreibt man diese auch normalerweise in den Beitrag rein damit andere mit demselben Problem eine Lösung haben.
Die Lösung wurde bereits weiter oben angesprochen. Mein Bild befand sich bloß im falschen Ordner. Nachdem ich es parallel zum Python-Arbeitsverzeichnis angelegt hatte lief alles gut.
Antworten