Tkinter: Jak wyświetlać obrazy
Przykładowe obrazki
Na początek kilka obrazków, które używam w przykładach. Mogą być ona przydatne przy testowaniu przykładów.



Wczytanie obrazka z tkinter.PhotoImage()
Tkinter używa PhotoImage do wczytania PNG, GIF lub PGM/PPM ale nie potrafi on wczytać JPG lub innego formatu. Starsze wersje nie potrafiły wczytać nawet PNG.
import tkinter as tk root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") # ... TODO: display image ... root.mainloop()
tkinter.PhotoImage musi być stworzony po tk.Tk(), który inicjuje pewne elementy potrzebne do wczytania obrazka.
tkinter.PhotoImage wymaga użycia nazwanej zmiennej file=. Jeśli się pominie tą nazwę zmiennej to wtedy próbuje on użyć nazwy pliku ze zmienną data=, która oczekuje obrazka w postaci tekstu zakodowanego z base64. Więcej o base64 string w innym poscie.
Aby wczytać JPG lub inny format trzeba użyć moduły pillow. Więcej o tym na końcu tej strony.
Wyświetlanie obrazka z użyciem Label
Tkinter może pokazać PhotoImage używając Label
import tkinter as tk root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") label = tk.Label(root, img) label.pack() root.mainloop()
Można także przypisać PhotoImage do już istniejącego Label używając
img = tk.PhotoImage(file="smile-1.png")
label["image"] = img
# or
label.config(image=img)
W ten sam sposób można też zamienić/podmienić obraz bez tworzenia nowego Label. Można to wykonać w funkcji wywołanej przez Button lub inny widżet, lub używając zdarzenia z bind(), lub używając czasu z after().
import tkinter as tk # --- functions --- def on_click(): global current_img # inform function to assing value to external/global variable if current_img == img1: current_img = img2 else: current_img = img1 label["image"] = current_img # --- main --- root = tk.Tk() img1 = tk.PhotoImage(file="smile-1.png") img2 = tk.PhotoImage(file="smile-2.png") current_img = img1 label = tk.Label(root, image=current_img) label.pack() button = tk.Button(root, text="Change", command=on_click) button.pack() root.mainloop()
Używając listy z obrazkami można by stworzyć przeglądarkę obrazków.
Wyświetlanie obrazka z użyciem Button
Tkinter` może pokazać ``PhotoImage używając Button
import tkinter as tk root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") button = tk.Button(root, image=img) button.pack() root.mainloop()
Można także przypisać PhotoImage do już istniejącego Button używając
img = tk.PhotoImage(file="smile-1.png")
button["image"] = img
# or
button.config(image=img)
W ten sam sposób można też zamienić/podmienić obraz bez tworzenia nowego Button. Można to wykonać w funkcji wywołanej przez Button lub inny widżet, lub używając zdarzenia z bind(), lub używając czasu z after().
import tkinter as tk # --- functions --- def on_click(): global current_img # inform function to assing value to external/global variable if current_img == img1: current_img = img2 else: current_img = img1 button["image"] = current_img # --- main --- root = tk.Tk() img1 = tk.PhotoImage(file="smile-1.png") img2 = tk.PhotoImage(file="smile-2.png") current_img = img1 button = tk.Button(root, image=current_img, command=on_click, compound="top", text="Image") button.pack() root.mainloop()
Używając listy z obrazkami można by stworzyć przeglądarkę obrazków.
Wyświetlanie obrazka z użyciem Canvas
Tkinter` może pokazać ``PhotoImage używając Canvas
import tkinter as tk root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") canvas = tk.Canvas(root) canvas.pack() img_id = canvas.create_image((0, 0), image=img, anchor='nw') root.mainloop()
Wymaga on pozycji (x, y) dla obrazka. Pozycja (0, 0) jest w górnym lewym rogu. Domyślnie umieszcza on środek obrazka we wskazanej pozycji ale można to zmienić za pomocą anchor=. Jeśli użyć anchor="nw" (nw = North West = Góra Lewy) to wtedy umieści górny lewy narożnik obrazka w pozycji (x, y)
create_image() dalej id obiektu stworzonego na płótnie i można go użyć z innymi funkcjami do usunięcia, zamiany lub przesunięcia obrazka.
import tkinter as tk import random # --- functions --- def on_click(): x = random.randint(0, 250) y = random.randint(0, 250) canvas.moveto(img_id, x, y) # --- main --- root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") canvas = tk.Canvas(root) canvas.pack() img_id = canvas.create_image((0, 0), image=img, anchor='nw') button = tk.Button(root, text="move", command=on_click) button.pack() root.mainloop()
Używając listy z obrazkami można by stworzyć przeglądarkę obrazków.
Używając przycisków i/lub after() można stworzyć animację lub grę.
import tkinter as tk import random # --- functions --- def move_image(): dx = random.randint(-10, 10) dy = random.randint(-10, 10) canvas.move(img_id, dx, dy) # move image again after 100ms (0.1s) root.after(100, move_image) # --- main --- root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") canvas = tk.Canvas(root) canvas.pack() img_id = canvas.create_image((100, 100), image=img) # move image first time #root.after(100, move_image) move_image() root.mainloop()
Wyświetlanie obrazka i tekstu z użyciem Label lub Button
Kiedy Label lub Button wyświetla obrazek wtedy nie pokazuje tekstu.
Aby wyświetlić tekst i obrazek w tym samym czasie wymage to użycia compound= aby zdefiniować gdzie ma być pokazany obrazek left, right, top, bottom lub center aby pokazać tekst na obrazku.
label = tk.Label(root, text="Image", image=img, compound="top")
button = tk.Butoon(root, text="Button", image=img, compound="top")
import tkinter as tk root = tk.Tk() img = tk.PhotoImage(file="smile-1.png") label = tk.Label(root, image=img, text='Hello') label.pack() label = tk.Label(root, image=img, text='left', compound='left') label.pack() label = tk.Label(root, image=img, text='right', compound='right') label.pack() label = tk.Label(root, image=img, text='top', compound='top') label.pack() label = tk.Label(root, image=img, text='bottom', compound='bottom') label.pack() label = tk.Label(root, image=img, text='center', compound='center', fg='red') label.pack() root.mainloop()

Wczytanie obrazka z ImageTk.PhotoImage()
Aby wczytać JPG lub innym format trzeba użyć ImageTk.PhotoImage() z modułu pillow. Oczywiście można go użyć także do wczytania PNG, GIF.
import tkinter as tk from PIL import ImageTk root = tk.Tk() img = ImageTk.PhotoImage(file="smile-1.png") label = tk.Label(root, image=img) label.pack() root.mainloop()
ImageTk.PhotoImage musi być stworzony po tk.Tk(), który inicjuje pewne elementy potrzebne do wczytania obrazka.
ImageTk.PhotoImage wymaga użycia nazwanej zmiennej file= aby wczytać bezpośrednio z pliku. If you skip this name then it tries to use with data= which needs pillow.Image which can be very useful.
Jeśli się pominie tą nazwę zmiennej to wtedy próbuje on użyć nazwy pliku ze zmienną data=, która oczekuje obrazka pillow.Image, który może być bardzo użyteczny. pillow ma funkcje do zmieniania wielkości, obracania, przycinania, zamiany kolorów, wstawiania jednego obrazka na drugi, a także do rysowania tekstu lub figur (z użyciem ImageDraw)
import tkinter as tk from PIL import Image, ImageTk image = Image.open("smile-1.png") image = image.resize((350, 350)).invert() root = tk.Tk() img = ImageTk.PhotoImage(image) label = tk.Label(root, image=img) label.pack() root.mainloop()
Błąd w PhotoImage
PhotoImage posiada się błąd, który powoduje usunięcie obrazka z pamięci (a co za tym idzie wyświetla puste miejsce) jeśli obraz został przypisany do lokalnej zmiennej stworzonej w funkcji lub w metodzie klasy.
PhotoImage musi zostać przypisany do zmiennej globalnej
def function():
global img
img = tk.PhotoImage(file="smile-1.png")
lub do dowolnej zmiennej w istniejącym obiekcie
def function():
img = tk.PhotoImage(file="smile-1.png")
label = tk.Label(image=img)
label.image = img # it can be different name - ie. `label.img`
label.pack()
lub z użyciem self. w klasie
class MyWindow:
def method(self):
self.img = tk.PhotoImage(file="smile-1.png")
Linki:
- [web.archive.org] effbot.org: PhotoImage
- [web.archive.org] effbot.org: Label
- [web.archive.org] effbot.org: Button
- [web.archive.org] effbot.org: Canvas
