Bagaimana cara saya menangani acara tutup jendela (pengguna mengklik tombol 'X') dalam program Python Tkinter?
131
Tkinter mendukung mekanisme yang disebut penangan protokol . Di sini, istilah protokol mengacu pada interaksi antara aplikasi dan window manager. Protokol yang paling umum digunakan disebut WM_DELETE_WINDOW
, dan digunakan untuk menentukan apa yang terjadi ketika pengguna secara eksplisit menutup jendela menggunakan window manager.
Anda dapat menggunakan protocol
metode ini untuk menginstal handler untuk protokol ini (widget harus a Tk
atau Toplevel
widget):
Di sini Anda memiliki contoh nyata:
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()
Tkinter
tidak memiliki kotak pesan submodule. Saya menggunakanimport tkMessageBox as messagebox
Matt telah menunjukkan satu modifikasi klasik dari tombol tutup.
Yang lain adalah memiliki tombol tutup meminimalkan jendela.
Anda dapat mereproduksi perilaku ini dengan memiliki metode iconify
menjadi argumen kedua metode protokol .
Berikut ini contoh yang berfungsi, diuji pada Windows 7 & 10:
Dalam contoh ini kami memberi pengguna dua opsi keluar baru:
File klasik → Keluar, dan juga Esctombol.
sumber
Bergantung pada aktivitas Tkinter, dan terutama ketika menggunakan Tkinter.setelah, menghentikan aktivitas ini dengan
destroy()
- bahkan dengan menggunakan protokol (), sebuah tombol, dll. - akan mengganggu aktivitas ini (kesalahan "saat menjalankan") daripada hanya menghentikannya . Solusi terbaik di hampir setiap kasus adalah menggunakan bendera. Ini adalah contoh sederhana dan konyol tentang cara menggunakannya (walaupun saya yakin sebagian besar dari Anda tidak membutuhkannya! :)Ini mengakhiri aktivitas grafik dengan baik. Anda hanya perlu memeriksa
running
di tempat yang tepat.sumber
Saya ingin mengucapkan terima kasih atas jawaban Apostolos yang telah menyampaikan ini kepada saya. Berikut adalah contoh yang jauh lebih terperinci untuk Python 3 di tahun 2019, dengan deskripsi dan contoh kode yang lebih jelas.
Waspadalah terhadap kenyataan bahwa
destroy()
(atau tidak memiliki penangan penutupan jendela khusus sama sekali) akan menghancurkan jendela dan semua callback yang berjalan instan ketika pengguna menutupnya.Ini bisa berdampak buruk bagi Anda, tergantung pada aktivitas Tkinter Anda saat ini, dan terutama saat menggunakan
tkinter.after
(panggilan balik berkala). Anda mungkin menggunakan panggilan balik yang memproses beberapa data dan menulis ke disk ... dalam hal ini, Anda jelas ingin penulisan data selesai tanpa terbunuh secara tiba-tiba.Solusi terbaik untuk itu adalah menggunakan bendera. Jadi, ketika pengguna meminta penutupan jendela, Anda menandainya sebagai bendera, dan kemudian bereaksi.
(Catatan: Saya biasanya mendesain GUI sebagai kelas yang dienkapsulasi dengan baik dan utas pekerja terpisah, dan saya jelas tidak menggunakan "global" (sebagai gantinya saya menggunakan variabel instance kelas), tetapi ini dimaksudkan sebagai contoh sederhana yang tidak perlu untuk menunjukkan bagaimana Tk tiba-tiba membunuh panggilan balik berkala Anda ketika pengguna menutup jendela ...)
Kode ini akan menunjukkan kepada Anda bahwa
WM_DELETE_WINDOW
pawang berjalan bahkan saat kebiasaan kamiperiodic_call()
sedang sibuk di tengah-tengah kerja / loop!Kami menggunakan beberapa
.after()
nilai yang cukup berlebihan : 500 milidetik. Ini hanya dimaksudkan untuk membuatnya sangat mudah bagi Anda untuk melihat perbedaan antara menutup sementara panggilan periodik sedang sibuk, atau tidak ... Jika Anda menutup ketika nomor sedang memperbarui, Anda akan melihat bahwa ituWM_DELETE_WINDOW
terjadi ketika panggilan periodik Anda "tadinya proses sibuk: Benar ". Jika Anda menutup sementara nomor dijeda (berarti bahwa panggilan balik periodik tidak diproses pada saat itu), Anda melihat bahwa penutupan terjadi ketika sedang "tidak sibuk".Dalam penggunaan di dunia nyata, Anda
.after()
akan menggunakan sesuatu seperti 30-100 milidetik, untuk memiliki GUI yang responsif. Ini hanya sebuah demonstrasi untuk membantu Anda memahami cara melindungi diri Anda dari perilaku standar Tk "segera hentikan semua pekerjaan saat menutup".Singkatnya: Buat
WM_DELETE_WINDOW
pawang mengatur bendera, dan kemudian periksa bendera itu secara berkala dan secara manual.destroy()
jendela itu aman (ketika aplikasi Anda selesai dengan semua pekerjaan).PS: Anda juga dapat menggunakan
WM_DELETE_WINDOW
untuk bertanya kepada pengguna apakah mereka BENAR-BENAR ingin menutup jendela; dan jika mereka menjawab tidak, Anda tidak mengatur benderanya. Ini sangat sederhana. Anda hanya menunjukkan kotak pesan di kotak AndaWM_DELETE_WINDOW
dan mengatur bendera berdasarkan jawaban pengguna.sumber
Coba Versi Sederhana:
Atau Jika Anda Ingin Menambahkan Perintah Lebih Banyak:
sumber
sumber