web-dev-qa-db-fra.com

Comment gérer l'événement de fermeture de fenêtre dans Tkinter?

Comment gérer l'événement de fermeture de la fenêtre (l'utilisateur clique sur le bouton 'X') dans un programme Python Tkinter?

100
Matt Gregory

Tkinter supporte un mécanisme appelé gestionnaires de protocole . Ici, le terme protocole fait référence à l'interaction entre l'application et le gestionnaire de fenêtres. Le protocole le plus couramment utilisé est appelé WM_DELETE_WINDOW, et sert à définir ce qui se passe lorsque l'utilisateur ferme explicitement une fenêtre à l'aide du gestionnaire de fenêtres.

Vous pouvez utiliser la méthode protocol pour installer un gestionnaire pour ce protocole (le widget doit être un Tk ou Toplevel widget):

Ici vous avez un exemple concret:

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()

def on_closing():
    if messagebox.askokcancel("Quit", "Do you want to quit?"):
        root.destroy()

root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
137
Matt Gregory

Matt a montré une modification classique du bouton de fermeture.
L’autre consiste à faire en sorte que le bouton de fermeture minimise la fenêtre.
Vous pouvez reproduire ce problème en utilisant la méthode iconify
soit le protocole deuxième argument de la méthode.

Voici un exemple de travail testé sur Windows 7:

# Python 3
import tkinter
import tkinter.scrolledtext as scrolledtext

class GUI(object):

    def __init__(self):
        root = self.root = tkinter.Tk()
        root.title('Test')

    # make the top right close button minimize (iconify) the main window
        root.protocol("WM_DELETE_WINDOW", root.iconify)

    # make Esc exit the program
        root.bind('<Escape>', lambda e: root.destroy())

    # create a menu bar with an Exit command
        menubar = tkinter.Menu(root)
        filemenu = tkinter.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Exit", command=root.destroy)
        menubar.add_cascade(label="File", menu=filemenu)
        root.config(menu=menubar)

    # create a Text widget with a Scrollbar attached
        txt = scrolledtext.ScrolledText(root, undo=True)
        txt['font'] = ('consolas', '12')
        txt.pack(expand=True, fill='both')

gui = GUI()
gui.root.mainloop()

Dans cet exemple, nous donnons à l'utilisateur deux nouvelles options de sortie:
le menu Fichier classique -> Quitter, ainsi que le Esc bouton.

21
Honest Abe

En fonction de l'activité de Tkinter, end esp. lorsque vous utilisez Tkinter.after, arrêter cette activité avec destroy(), même en utilisant protocol (), un bouton, etc. - perturbera cette activité (erreur "en cours d'exécution") plutôt que de la terminer. La meilleure solution dans presque tous les cas consiste à utiliser un drapeau. Voici un exemple simple et stupide d'utilisation (bien que je sois certain que la plupart d'entre vous n'en ont pas besoin! :)

from Tkinter import *

def close_window():
  global running
  running = False
  print "Window closed"

root = Tk()
root.protocol("WM_DELETE_WINDOW", close_window)
cv = Canvas(root, width=200, height=200); cv.pack()

running = True;
# This is an endless loop stopped only by setting 'running' to 'False'
while running: 
  for i in range(200): 
    if not running: break
    cv.create_oval(i,i,i+1,i+1); root.update() 

Cela met fin à l'activité graphique bien. Il vous suffit de vérifier running au bon endroit.

4
Apostolos

Essayez la version simple:

import tkinter

window = Tk()

closebutton = Button(window, text='X', command=window.destroy)
closebutton.pack()

window.mainloop()

Ou si vous souhaitez ajouter plus de commandes:

import tkinter

window = Tk()


def close():
    window.destroy()
    #More Functions


closebutton = Button(window, text='X', command=close)
closebutton.pack()

window.mainloop()
0
SF12 Study