Python >> Tutoriel Python >  >> Python GUI >> Tkinter GUI

Développement d'interface graphique Python avec Tkinter

Il s'agit du premier volet de notre série en plusieurs parties sur le développement d'interfaces graphiques en Python à l'aide de Tkinter. Consultez les liens ci-dessous pour les prochaines parties de cette série :

  • Développement d'interface graphique Python avec Tkinter
  • Développement d'une interface graphique Python avec Tkinter : 2e partie
  • Développement d'une interface graphique Python avec Tkinter : 3e partie

Introduction

Si vous lisez cet article, il y a de fortes chances que vous fassiez partie de ces personnes qui apprécient les logiciels fonctionnant via une simple interface de ligne de commande. C'est rapide, facile sur les ressources de votre système, et probablement beaucoup plus rapide à utiliser pour un virtuose du clavier comme vous. Cependant, ce n'est un secret pour personne que si nous voulons atteindre une base d'utilisateurs plus large avec notre logiciel, offrir uniquement une solution en ligne de commande pourrait effrayer une grande partie des utilisateurs potentiels. Pour la plupart des gens, la manière la plus évidente d'interagir avec un programme consiste à utiliser une GUI – une interface utilisateur graphique .

Lors de l'utilisation d'une interface graphique, l'utilisateur interagit avec et manipule les éléments de l'interface appelés widgets . Certains widgets, comme les boutons et les cases à cocher, permettent à l'utilisateur d'interagir avec le programme. D'autres, comme les fenêtres et les cadres, servent de conteneurs pour d'autres widgets.

Il existe de nombreux packages pour créer des interfaces graphiques en Python, mais un seul de ces packages est considéré comme un de facto standard et est distribué avec toutes les installations Python par défaut. Ce paquet s'appelle Tkinter. Tkinter est la liaison de Python à Tk - une boîte à outils d'interface graphique open source et multiplateforme.

Création de votre première fenêtre

Comme mentionné précédemment, Tkinter est disponible avec les installations Python standard, donc quel que soit votre système d'exploitation, la création de votre première fenêtre devrait être très rapide. Vous n'avez besoin que de 3 lignes de code :

import tkinter

root = tkinter.Tk()

root.mainloop()

Sortie :

Après avoir importé le tkinter package à la ligne 1, à la ligne 3, nous créons le widget de la fenêtre principale (racine) de notre application. Pour que le programme fonctionne correctement, il ne devrait y avoir qu'un seul widget de fenêtre racine dans notre interface, et, comme tous les autres widgets seront plus bas dans la hiérarchie que root, il doit être créé avant tout autre widget.

A la ligne 5, on initialise le mainloop de la racine . Grâce à cette ligne, la fenêtre reste dans une boucle qui attend des événements (tels que l'interaction de l'utilisateur) et met à jour l'interface en conséquence. La boucle se termine lorsque l'utilisateur ferme la fenêtre, ou un quit() méthode est appelée.

Ajout de widgets simples à la fenêtre racine

Dans l'exemple suivant, nous allons apprendre la philosophie générale en deux étapes de la création de widgets, qui peut être appliquée à tous les widgets à l'exception des fenêtres. La première étape consiste à créer une instance de la classe d'un widget spécifique. Dans la deuxième étape, nous devons utiliser l'une des méthodes disponibles pour placer le nouveau widget dans un autre widget déjà existant (un parent widget). Le widget le plus simple que vous puissiez mettre dans votre interface Tkinter est un label , qui affiche simplement du texte. L'exemple suivant crée un widget d'étiquette simple :

import tkinter

root = tkinter.Tk()

simple_label = tkinter.Label(root, text="Easy, right?")

simple_label.pack()

root.mainloop()

Sortie :

Nous créons le Label instance de classe à la ligne 5 du code ci-dessus. Dans le premier argument, nous pointons vers le widget parent souhaité de l'étiquette, qui dans cet exemple est notre fenêtre racine. Dans le deuxième argument, nous spécifions le texte que nous voulons que l'étiquette affiche.

Ensuite, à la ligne 7, nous appliquons une méthode d'orientation de notre étiquette à l'intérieur de la fenêtre racine. La méthode la plus simple d'orientation des widgets proposée par Tkinter est pack() . L'étiquette est le seul widget à l'intérieur de la fenêtre, elle est donc simplement affichée au milieu de la fenêtre.

Nous en apprendrons plus sur son fonctionnement dans l'exemple suivant, lorsque nous ajouterons un autre widget à la fenêtre. Notez que la taille de la fenêtre s'ajuste automatiquement au widget placé à l'intérieur.

Ajouter un bouton fonctionnel

Maintenant, ajoutons quelque chose avec lequel l'utilisateur peut interagir. Le choix le plus évident est un simple bouton. Mettons un bouton dans notre fenêtre qui nous donne un moyen supplémentaire de fermer notre fenêtre.

import tkinter

root = tkinter.Tk()

root.title("Hello!")

simple_label = tkinter.Label(root, text="Easy, right?")
closing_button = tkinter.Button(root, text="Close window", command=root.destroy)

simple_label.pack()
closing_button.pack()

root.mainloop()

Sortie :

À la ligne 8, nous créons notre Button instance de classe d'une manière très similaire, nous avons créé notre étiquette. Comme vous pouvez probablement le voir, cependant, nous avons ajouté un argument de commande dans lequel nous indiquons au programme ce qui doit se passer après avoir cliqué sur le bouton. Dans ce cas root est dramatique destroy() méthode est appelée, ce qui fermera notre fenêtre lors de son exécution.

Aux lignes 10 et 11, nous utilisons à nouveau le pack() méthode. Cette fois, nous pouvons le comprendre un peu mieux, car nous l'utilisons maintenant pour placer deux widgets à l'intérieur de la fenêtre. Selon l'ordre dans lequel nous emballons nos widgets, la méthode les lance simplement les uns sur les autres, centrés horizontalement. La hauteur et la largeur de la fenêtre s'adaptent à la taille des widgets.

Vous avez probablement remarqué une autre nouvelle ligne. À la ligne 5, nous spécifions le titre de la fenêtre racine . Malheureusement, le widget le plus large de notre interface n'est pas assez large pour que le titre de la fenêtre devienne visible. Faisons quelque chose.

Contrôle de la taille de la fenêtre

Jetons un coup d'œil à trois nouvelles lignes qui nous permettront de redimensionner facilement notre fenêtre.

import tkinter

root = tkinter.Tk()

root.title("Hello!")

root.resizable(width="false", height="false")

root.minsize(width=300, height=50)
root.maxsize(width=300, height=50)

simple_label = tkinter.Label(root, text="Easy, right?")
closing_button = tkinter.Button(root, text="Close window", command=root.destroy)

simple_label.pack()
closing_button.pack()

root.mainloop()

Sortie :

À la ligne 7, nous définissons si l'utilisateur du programme doit pouvoir modifier la largeur et la hauteur de la fenêtre . Dans ce cas, les deux arguments sont définis sur "false" , donc la taille de la fenêtre ne dépend que de notre code. S'il n'y avait pas les lignes 9 et 10, cela dépendrait de la taille des widgets orientés à l'intérieur de la fenêtre.

Cependant, dans cet exemple, nous utilisons le minsize de root et maxsize méthodes pour contrôler les valeurs maximales et minimales de la largeur et de la hauteur de notre fenêtre. Ici, nous définissons exactement la largeur et la hauteur de la fenêtre, mais je vous encourage à jouer avec ces trois lignes pour voir comment fonctionne le redimensionnement en fonction de la taille de nos widgets et des valeurs minimales et maximales que nous définissons.

En savoir plus sur l'orientation des widgets

Comme vous l'avez probablement déjà remarqué, en utilisant le pack() La méthode ne nous donne pas trop de contrôle sur l'endroit où les widgets se retrouvent après les avoir emballés dans leurs conteneurs parents. Pour ne pas dire le pack() La méthode n'est pas prévisible - c'est juste qu'évidemment, parfois jeter des widgets dans la fenêtre dans une seule colonne, où un widget est placé au-dessus du précédent, n'est pas nécessairement cohérent avec notre sens sophistiqué de l'esthétique. Dans ces cas, nous pouvons soit utiliser pack() avec quelques arguments intelligents, ou utilisez grid() – une autre méthode d'orientation des widgets à l'intérieur des conteneurs.

D'abord, donnons peut-être pack() une chance de plus. En modifiant les lignes 15 et 16 de l'exemple précédent, nous pouvons légèrement améliorer notre interface :

simple_label.pack(fill="x")
closing_button.pack(fill="x")

Sortie :

De cette manière simple, nous disons au pack() méthode pour étirer l'étiquette et le bouton tout le long de l'axe horizontal. On peut aussi changer le chemin pack() jette de nouveaux widgets à l'intérieur de la fenêtre. Par exemple, en utilisant l'argument suivant :

simple_label.pack(side="left")
closing_button.pack(side="left")

Sortie :

Nous pouvons regrouper les widgets dans la même ligne, en commençant par le côté gauche de la fenêtre. Cependant, pack() n'est pas la seule méthode d'orientation des widgets à l'intérieur de leurs widgets parents. La méthode qui donne les plus beaux résultats est probablement la grid() méthode, qui nous permet de classer les widgets en lignes et en colonnes. Jetez un oeil à l'exemple suivant.

import tkinter

root = tkinter.Tk()

simple_label = tkinter.Label(root, text="Easy, right?")
another_label = tkinter.Label(root, text="More text")
closing_button = tkinter.Button(root, text="Close window", command=root.destroy)
another_button = tkinter.Button(root, text="Do nothing")

simple_label.grid(column=0, row=0, sticky="ew")
another_label.grid(column=0, row=1, sticky="ew")
closing_button.grid(column=1, row=0, sticky="ew")
another_button.grid(column=1, row=1, sticky="ew")

root.mainloop()

Sortie :

Pour rendre cet exemple un peu plus clair, nous nous sommes débarrassés des lignes qui modifiaient le titre et la taille de la fenêtre racine. Aux lignes 6 et 8, nous avons ajouté une autre étiquette et un autre bouton (notez que cliquer dessus ne fera rien car nous n'y avons attaché aucune commande).

Mais le plus important, pack() a été remplacé par grid() dans tous les cas. Comme vous pouvez probablement le comprendre facilement, les arguments column et row définissons quelle cellule de la grille notre widget occupera. Gardez à l'esprit que si vous définissez les mêmes coordonnées pour deux widgets différents, celui rendu plus loin dans votre code sera affiché au-dessus de l'autre.

Le sticky l'argument n'est probablement pas aussi évident. En utilisant cette option, nous pouvons coller les bords de nos widgets aux bords de leurs cellules de grille respectives - n orthern (supérieur), s sud (en bas), e arrière (droite) et w est (à gauche). Nous faisons cela en passant une chaîne simple qui contient une configuration de lettres n , s , e et w .

Dans notre exemple, nous collons les bords des quatre widgets à l'est de leurs cellules et occidental bords, donc la chaîne est ew . Il en résulte que les widgets sont étirés horizontalement. Vous pouvez jouer avec différentes configurations de ces quatre lettres. Leur ordre dans la chaîne n'a pas d'importance.

Maintenant que vous connaissez deux méthodes différentes pour orienter les widgets, gardez à l'esprit que vous ne devez jamais mélanger grid() et pack() à l'intérieur du même conteneur.

Cadres

Windows ne sont pas les seuls widgets qui peuvent contenir d'autres widgets. Afin de rendre vos interfaces complexes plus claires, il est généralement judicieux de séparer vos widgets en cadres .

Essayons de le faire avec nos quatre widgets simples :

import tkinter

root = tkinter.Tk()

frame_labels = tkinter.Frame(root, borderwidth="2", relief="ridge")
frame_buttons = tkinter.Frame(root, borderwidth="2", relief="ridge")

simple_label = tkinter.Label(frame_labels, text="Easy, right?")
another_label = tkinter.Label(frame_labels, text="More text")

closing_button = tkinter.Button(frame_buttons, text="Close window", command=root.destroy)
another_button = tkinter.Button(frame_buttons, text="Do nothing")

frame_labels.grid(column=0, row=0, sticky="ns")
frame_buttons.grid(column=1, row=0)

simple_label.grid(column=0, row=0, sticky="ew")
another_label.grid(column=0, row=1, sticky="ew")

closing_button.pack(fill="x")
another_button.pack(fill="x")

root.mainloop()

Sortie :

Examinons attentivement l'exemple ci-dessus. Aux lignes 5 et 6 nous définissons deux nouveaux Frame widgets. Évidemment, dans le premier argument, nous pointons vers leur widget parent, qui est la fenêtre racine.

Par défaut, les bordures des cadres sont invisibles, mais disons que nous aimerions voir exactement où elles sont placées. Afin de montrer leurs bordures, nous devons leur donner une certaine largeur (dans notre exemple, 2 pixels) et le style de relief (une sorte d'effet 3D) dans lequel la bordure sera dessinée. Vous avez le choix entre 5 styles de relief différents - dans notre exemple, nous utilisons ridge .

Label et Button les définitions ont également été légèrement modifiées (lignes 8-12). Nous voulions placer nos étiquettes dans notre frame_labels cadre et nos boutons dans notre frame_buttons Cadre. Ainsi, nous avons dû remplacer leur parent précédent, root , avec leurs nouveaux cadres parents respectifs.

Aux lignes 14 et 15, nous orientons les cadres à l'intérieur de la fenêtre racine en utilisant le grid() méthode. Ensuite, nous utilisons le grid() méthode pour orienter les étiquettes (lignes 17-18), et le pack() méthode pour orienter les boutons (lignes 20-21). Les étiquettes et les boutons sont maintenant dans des conteneurs séparés, donc rien ne nous empêche d'orienter les widgets en utilisant différentes méthodes.

Fenêtres de niveau supérieur

Votre interface ne doit pas contenir plus d'une fenêtre racine, mais vous pouvez créer plusieurs fenêtres enfants de la fenêtre racine. La meilleure façon de le faire est d'utiliser le Toplevel classe.

import tkinter

root = tkinter.Tk()

new_window = tkinter.Toplevel()
new_window.withdraw()

frame_labels = tkinter.Frame(root, borderwidth="2", relief="ridge")
frame_buttons = tkinter.Frame(root, borderwidth="2", relief="ridge")

simple_label = tkinter.Label(frame_labels, text="Easy, right?")
another_label = tkinter.Label(frame_labels, text="More text")

closing_button = tkinter.Button(frame_buttons, text="Close window", command=root.destroy)
window_button = tkinter.Button(frame_buttons, text="Show new window", command=new_window.deiconify)

frame_labels.grid(column=0, row=0, sticky="ns")
frame_buttons.grid(column=1, row=0)

simple_label.grid(column=0, row=0, sticky="ew")
another_label.grid(column=0, row=1, sticky="ew")

closing_button.pack(fill="x")
window_button.pack(fill="x")

root.mainloop()

Dans l'exemple ci-dessus, nous créons notre nouvelle fenêtre à la ligne 5. Parce qu'une fenêtre est une entité qui n'est ancrée à l'intérieur d'aucun autre widget, nous n'avons pas besoin de pointer vers son parent, ni de l'orienter à l'intérieur d'un widget parent.

Nous aimerions afficher la nouvelle fenêtre après avoir appuyé sur un bouton. La ligne 5 l'affiche tout de suite, nous utilisons donc le withdraw() méthode à la ligne 6 afin de la masquer. Nous modifions ensuite la définition du bouton à la ligne 15.

Outre le nouveau nom de variable et le texte, le bouton exécute maintenant une commande - le new_window méthode de l'objet, deiconify , ce qui fera réapparaître la fenêtre après que l'utilisateur ait cliqué sur le window_button bouton.

Interface graphique Python :de A à Z

Vous voulez en savoir plus sur la création d'interfaces graphiques en Python et sur les outils à votre disposition, comme Tkinter ? Essayez de suivre une formation étape par étape pour vous apprendre à créer rapidement des interfaces graphiques pour vos applications !

Conclusions

Comme vous pouvez le voir, en utilisant Tkinter, vous pouvez facilement et rapidement créer des interfaces graphiques pour les utilisateurs non experts de votre logiciel. La bibliothèque est incluse dans toutes les installations de Python, donc la construction de votre première fenêtre simple ne nécessite que quelques lignes de code. Les exemples ci-dessus effleurent à peine la surface des capacités du package.

Continuez à lire et consultez la deuxième partie de ce didacticiel Tkinter, qui vous apprendra à créer des interfaces utilisateur graphiques complexes, intuitives et jolies.