Note d'introduction Python Tkinter

Contexte

--Visual Studio (VB.NET), Android Studio (Java), XCode (Swift) sont faciles à développer / développer une interface graphique avec le concepteur GUI standard (l'application de bureau migre de VB.NET vers Java, C # est Unity Je l'utilise seulement) --En Java, AWT / Swing a été construit comme une interface graphique sans utiliser de concepteur (mise en page) ―― Depuis que le langage principal est passé de Java à Python, je n'ai fait que des outils CUI / Web, donc je veux également créer une interface graphique de bureau.

Ce n'est pas très performant (il y a des inconvénients en termes de transparence et de fonctions standards), mais comme c'est standard, je vais le résumer pour moi-même sous forme de mémorandum.

Quand j'essaye de quitter avec \ # Ctrl + C, il est ennuyeux qu'il ne réponde pas tant que je n'ai pas touché la fenêtre

Créer une fenêtre

import tkinter as tk

root = tk.Tk() # Window
root.title('Hello Window') # Window title
root.geometry('%dx%d' % (400, 400)) # Window size (width, height)

#Initialisez et placez le widget ici

root.mainloop()

Bloquer avec root.mainloop (). Quittez la boucle principale lorsque la fenêtre est fermée.

Boucle principale

Pour être précis, Tk semble gérer la boucle principale de Tkinter plutôt que Window. Vous pouvez créer les deuxième et troisième fenêtres avec tk.Toplevel lorsque vous créez des fenêtres multiples pour utiliser modal etc. (équivalent à Form = VB.NET, Frame = Java). Dans le cas de Java, je m'en fichais car je pense que le thread qui exécute la boucle pour l'interface graphique se lève (il reste en vie même si le thread principal qui exécute la fonction principale se termine), mais dans le cas de Tkinter, il est explicite. Il semble être géré de manière ciblée.

Si vous ne voulez pas que Tk existe en tant que fenêtre racine (en utilisant tk.Toplevel), vous pouvez le supprimer avec root.withdraw (). Cependant, la logique de "Fenêtre fermée = Fin de la boucle principale = Fin du programme" ne fonctionnera pas (rappelle la DefaultCloseOperation de Swing), donc root.destroy (me rappelle la DefaultCloseOperation de Swing) lorsque l'application se termine. ) Appelez.

Créer une application avec la fenêtre racine masquée

Affichez une fenêtre avec tk.Toplevel pour que la boucle principale se termine lorsqu'une fenêtre spécifique est fermée.

import tkinter as tk

root = tk.Tk()
root.withdraw()

window = tk.Toplevel(root)
window.title('Hello Window')
window.geometry('%dx%d' % (400, 400))
window.protocol('WM_DELETE_WINDOW', root.destroy)

#Initialisez et placez le widget ici

root.mainloop()

La fermeture de window peut être détectée par window.protocol ('WM_DELETE_WINDOW', handler_func) (correspondant à WindowListener \ #windowClosing of Swing).

window.protocol('WM_DELETE_WINDOW', root.destroy)

Après tout, dans une application comme une seule fenêtre + modale, il serait plus simple de traiter Tk comme la fenêtre principale avec obéissance.

Placement du cadre

frame = tk.Frame(root)
# frame = tk.Frame(root, bg='#FF00FF')
# frame['bg'] = '#FF00FF'
frame.place(x=8, y=8, width=200, height=200)

Panel(VB.NET/Java)/UIView(iOS)/ViewGroup(Android)的なやつ。Widgetのコンストラクタにbgとしてカラーコードを渡すと背景色を設定できる。初期化後に背景色を設定したい場合はディスクリプタ経由(widget['bg'])で設定できる。

Label Label(VB.NET/Java)/UILabel(iOS)/TextView(Android)的なやつ。

label = tk.Label(root, text='Hello')
# label['text'] = 'Another text'
label.place(x=8, y=8)

Bouton et gestionnaire d'événements

def onHelloClicked(event):
    print(event) # <ButtonPress event num=BUTTON_NUM x=MOUSE_X y=MOUSE_Y>
    # print(event.x, event.y, event.num)

button = tk.Button(root, text='Hello')
# button = tk.Button(root, text='Hello', width=10)
# button['text'] = 'Another text'

button.bind('<Button-1>', onHelloClicked)
# button.bind('<Button-2>', onHelloClicked)
# button.bind('<Button-3>', onHelloClicked)
# button.bind('<Button>', onHelloClicked)

button.place(x=8, y=8)
# button.place(x=8, y=8, width=60)
# button.place(x=8, y=8, width=60, height=31)

Vous pouvez passer width au constructeur de Widget, mais l'unité n'est pas en pixel et c'est difficile à comprendre (nombre de caractères?).

Vous pouvez enregistrer un gestionnaire d'événements avec bind. <Button - *> représente un clic sur le bouton de la souris (déroutant, mais sans rapport avec le tk.Button du widget). Faites un clic gauche sur «», cliquez avec le bouton central sur «» et faites un clic droit sur «». Le numéro du bouton est entré dans ʻevent.num (ʻevent.num = 1 lors d'un clic gauche, ʻevent.num = 3lors d'un clic droit. C'est déroutant, mais pas le nombre de clics). Vous pouvez également obtenir tous les clics de souris en spécifiant