Nous sommes aujourd'hui réunis suite à un terrible constat : notre visionneuse tkv craint un max.
C'est pourquoi nous allons ajouter une toute petite option nous permettant de choisir l'image que l'on souhaite visualiser sur notre ordinateur. Cela nous permettra par la même occasion de nous débarasser de certains morceaux qui ne sont plus utiles.

Profitons des dialogues déjà prêts dans la bibliothèque de tkinter en important celle qui nous intéresse :

from tkinter import filedialog

Nous pouvons à la place du téléchargement de l'image appeler une fenêtre de dialogue pour demander l'image à ouvrir :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\
        initialdir=(os.path.expanduser("~")),\
        title="Image à ouvrir",\
        parent=w)

Notez ici plusieurs options :

  • initialdir : Le répertoire de départ où on propose des fichiers à ouvrir. Là, je me sert de os pour afficher le répartoire personnel de l'utilisateur repéré par ~ sous UNIX.
  • title : Le titre de notre fenêtre.
  • parent : La fenêtre dont dépend le dialogue.

Cela ne sufit pas, il faudrait proposer seulement les fichiers qui sont des images. On va donc indiquer les motifs qui nous intéressent (pattern). En gros, ce sont juste les extensions :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\
        initialdir=(os.path.expanduser("~")),\
        filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\
        title="Image à ouvrir",\
        parent=w)

On ajoute quand même un petit test pour vérifier que on a bien sélectionné un fichier valide. On utilise la bibliothque "mimetypes" qui est livrée par défaut avec python, et on regarde si le mot "image" apparait dans le type du fichier.
Pour afficher l'erreur, on utilise une fenêtre de dialogue livré avec tkinter après avoir importé la partie qui nous intéresse :

mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")

Et voilà !

Remarquez qu'il existe un tas de fenêtres de dialogue déjà toutes prêtes pour afficher des avertissements (showwarning) ou des informations (showinfo) ou de poser une simple question (askquestion). Regardez par ici pour plus de détails : http://effbot.org/tkinterbook/tkinter-standard-dialogs.htm .

Je vais rajouter quelques lignes pour afficher une image si elle est passée en argument (par exemple en faisant tkv /home/bibi/image.jpg) :


# Ouverture de l'image
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]
else:
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\
    # ...
    # ...

Il reste encore quelques points à améliorer, mais ça reste déjà plus pratique. ^^
Ça sera tout pour aujourd'hui.
La prochaine fois, nous ajouterons quelques boutons à notre visionneuse d'images :)

Voici le code final :


#!/usr/bin/env python
# -*- coding:Utf-8 -*- 

import os
import sys
import mimetypes
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk


# Notre fenêtre principale
w = Tk()
w.title("tkv : visionneuse d'images") # Un titre
w.configure(background='#000000')     # Fond noir

# Un conteneur dans la fenêtre
mainframe = Frame(w)
mainframe.pack(fill=BOTH,expand=True, padx=15, pady=15)

# Ouverture de l'image
img_path=""
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]

if not os.path.isfile(img_path):
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\
            initialdir=(os.path.expanduser("~")),\
            filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\
            title="Image à ouvrir",\
            parent=w)

# Est-ce un fichier valide ?
mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")
    sys.exit(1)

# Ouverture de l'image
image = Image.open(img_path)
# Dimensions de l'écran : 
gap = 100 # marge par rapport aux bordes de l'écran
screen_width = w.winfo_screenwidth() - gap
screen_height = w.winfo_screenheight() - gap

if image.width > screen_width : 
    image = image.resize((screen_width, int(image.height * screen_width / image.width)), Image.ANTIALIAS)
if image.height > screen_height :   
    image = image.resize((int(image.width * screen_height / image.height), screen_height), Image.ANTIALIAS)

# Chargement de l'image en mémoire
img = ImageTk.PhotoImage(image)

# Insertion de l'image dans le conteneur.
img_widget = Label(mainframe, image=img)
img_widget.pack()

# Démarrage du programme
w.mainloop()

sys.exit(0)