In einem älteren Artikel ging es um die Python-Bibliothek Pillow, die in Python die Bildbearbeitung ermöglicht. Um diese Bibliothek geht es auch in diesem Tutorial, wobei in diesem Fall ein Bild über eine grafischen Benutzeroberfläche geöffnet und angezeigt werden soll.
Erstellt zunächst ein neues Python-Projekt, wobei es sinnvoll ist, dafür eine virtuelle Umgebung zu verwenden. In diesem Artikel wird erklärt, wie man eine virtuelle Umgebung für Python erstellen kann.
Der Datei, die den Code enthalten soll, habe ich den Namen main.py gegeben. Sie enthält diese Import-Anweisungen:
import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTkDamit das Bild angezeigt werden kann wird Pillow benötigt. Die Installation kann mit pip durchgeführt werden:
python3 -m pip install --upgrade Pillow # macOS, Linux
python -m pip install --upgrade Pillow # WindowsLeeres Fenster erstellen
In der Datei main.py wird zunächst mithilfe von Tkinter ein leeres Fenster erstellt. In diesem Fenster soll später das geöffnete Bild angezeigt werden. Da ich Tkinter bereits in anderen Blogbeiträgen erklärt habe, werde ich auf den Code nicht im Detail eingehen.
class MainWindow:
def __init__(self) -> None:
self.window = tk.Tk()
self.window.title("Image Tool")
window_width = 800
window_height = 600
screen_width = self.window.winfo_screenwidth()
screen_height = self.window.winfo_screenheight()
center_x = int(screen_width / 2 - window_width / 2)
center_y = int(screen_height / 2 - window_height / 2)
self.window.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
self.window.resizable(True, True)
def mainloop(self):
self.window.mainloop()
if __name__ == "__main__":
app_instance = MainWindow()
app_instance.mainloop()Nach der Ausführung dieses Codes wird ein leeres Fenster angezeigt. Nachfolgende Abbildung zeigt, wie dieses Fenster in Windows 11 aussieht.
Bilddatei öffnen
Zunächst wird ein Container erstellt, der dann ein Label für das geöffnete Bild und zwei Buttons enthalten soll.
# Hauptcontainer für das Bild und die Buttons
self.content_frame = ttk.Frame(self.window)
self.content_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)Der Code für das Label sieht wie folgt aus:
# Label für das Bild
self.image_label = tk.Label(self.content_frame, text="Kein Bild ausgewählt")
self.image_label.pack(expand=True, fill=tk.BOTH)Unterhalb dieses Labels sollen die Buttons angezeigt werden, wobei diese in diesem Beispiel in einem Container „verpackt“ werden (ttk.Frame). Beginnen wir mit diesem Container:
# Container für die Buttons
self.button_frame = ttk.Frame(self.window)
self.button_frame.pack(side=tk.BOTTOM, pady=10)Nun kommen die Buttons hinzu („Bild auswählen“ und „Beenden“):
# Button zum Auswählen eines Bildes
self.select_button = ttk.Button(
self.button_frame, text="Bild auswählen", command=self.load_image
)
self.select_button.grid(row=0, column=0, padx=5)
# Button zum Beenden des Programms
self.quit_button = ttk.Button(
self.button_frame, text="Beenden", command=self.quit_program
)
self.quit_button.grid(row=0, column=2, padx=5)Durch einen Klick auf „Bild auswählen“ wird die Funktion load_image aufgerufen. Ein Klick auf „Beenden“ ruft quit_program auf. Beide Funktionen existieren bisher nicht, so dass derzeit noch Fehlermeldungen angezeigt werden. Dies ändern wir nun:
def load_image(self):
pass
def quit_program(self):
self.window.destroy()Nach der Ausführung des bisherigen Codes erhalten wir folgendes Fenster:
Durch die Zeile self.window.destroy() in der Funktion quit_program() wird das Programm beendet. Die Funktion load_image() enthält bisher aber nur pass als Platzhalter. Hier wird nun die Logik für das Öffnen eines Bildes hinzugefügt. Folgender Code führt dazu, dass nach einem Klick auf „Bild auswählen“ ein Fenster geöffnet wird, über das ein Bild ausgewählt werden kann. In diesem Beispiel werden die Dateiformate jpg und png unterstützt.
def load_image(self, file_path=None):
if file_path is None:
filetypes = [
("Image files", "*.png *.jpg *.jpeg),
("PNG", "*.png"),
("JPEG", "*.jpg *.jpeg"),
("All files", "*.*"),
]
file_path = filedialog.askopenfilename(
title="Bild auswählen", filetypes=filetypes
)
if not file_path:
returnEin Klick auf „Öffnen“ hat bisher aber keine Auswirkungen. Folgender Code ändert dies:
try:
image = Image.open(file_path)
image.thumbnail(
(self.content_frame.winfo_width(), self.content_frame.winfo_height())
)
self.photo = ImageTk.PhotoImage(image)
self.image_label.config(image=self.photo, text="")
except Exception as e:
print(f"Error loading image: {e}")Das Programm ist damit fertig, wenn auch nicht perfekt. Es ließen sich noch einige Verbesserungen vornehmen. So könnte man beispielsweise für den Fall, dass beim Öffnen eines Bildes ein Fehler auftritt, den Benutzer in einem separaten Fenster darauf informieren. Des Weiteren werden beim Verändern der Fenstergröße unter Umständen die Buttons verdeckt. Auch dies ließe sich ändern. An dieser Stelle wollen wir es aber dabei belassen. Es sei euch überlassen, dieses Programm weiterzuentwickeln.
Zum Schluß nochmal der komplette Code:
import tkinter as tk
from tkinter import filedialog, ttk
from PIL import Image, ImageTk
class MainWindow:
def __init__(self) -> None:
self.window = tk.Tk()
self.window.title("Image Tool")
window_width = 800
window_height = 600
screen_width = self.window.winfo_screenwidth()
screen_height = self.window.winfo_screenheight()
center_x = int(screen_width / 2 - window_width / 2)
center_y = int(screen_height / 2 - window_height / 2)
self.window.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
self.window.resizable(True, True)
# Hauptcontainer für das Bild und die Buttons
self.content_frame = ttk.Frame(self.window)
self.content_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
# Label für das Bild
self.image_label = tk.Label(self.content_frame, text="Kein Bild ausgewählt")
self.image_label.pack(expand=True, fill=tk.BOTH)
# Container für die Buttons
self.button_frame = ttk.Frame(self.window)
self.button_frame.pack(side=tk.BOTTOM, pady=10)
# Button zum Auswählen eines Bildes
self.select_button = ttk.Button(
self.button_frame, text="Bild auswählen", command=self.load_image
)
self.select_button.grid(row=0, column=0, padx=5)
# Button zum Beenden des Programms
self.quit_button = ttk.Button(
self.button_frame, text="Beenden", command=self.quit_program
)
self.quit_button.grid(row=0, column=2, padx=5)
def load_image(self, file_path=None):
if file_path is None:
filetypes = [
("Image files", "*.png *.jpg *.jpeg *.heic *.HEIC *.heif *.HEIF"),
("PNG", "*.png"),
("JPEG", "*.jpg *.jpeg"),
("All files", "*.*"),
]
file_path = filedialog.askopenfilename(
title="Bild auswählen", filetypes=filetypes
)
if not file_path:
return
try:
image = Image.open(file_path)
image.thumbnail(
(self.content_frame.winfo_width(), self.content_frame.winfo_height())
)
self.photo = ImageTk.PhotoImage(image)
self.image_label.config(image=self.photo, text="")
except Exception as e:
print(f"Error loading image: {e}")
def quit_program(self):
self.window.destroy()
def mainloop(self):
self.window.mainloop()
if __name__ == "__main__":
app_instance = MainWindow()
app_instance.mainloop()

