programing

Tkinter에서 윈도우 닫기 이벤트는 어떻게 처리합니까?

showcode 2023. 6. 14. 22:01
반응형

Tkinter에서 윈도우 닫기 이벤트는 어떻게 처리합니까?

Python Tkinter 프로그램에서 창 닫기 이벤트(사용자가 'X' 버튼을 클릭)를 어떻게 처리합니까?

Tkinter는 프로토콜 핸들러라는 메커니즘을 지원합니다.여기서 프로토콜이라는 용어는 응용 프로그램과 창 관리자 간의 상호 작용을 나타냅니다.가장 일반적으로 사용되는 프로토콜은 다음과 같습니다.WM_DELETE_WINDOW사용자가 창 관리자를 사용하여 창을 명시적으로 닫을 때 수행되는 작업을 정의하는 데 사용됩니다.

당신은 할 수 .protocol이 프로토콜에 대한 처리기를 설치하는 방법(위젯은 반드시Tk또는Toplevel위젯):

여기 구체적인 예가 있습니다.

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()

Matt는 Close 버튼을 고전적으로 수정한 것을 보여주었습니다.
다른 하나는 닫기 버튼을 사용하여 창을 최소화하는 것입니다.
아이콘화 방법을 사용하여 이 동작을 재현할 수 있습니다.
프로토콜 방법의 두 번째 인수입니다.

다음은 Windows 7 및 10에서 테스트된 작동 예입니다.

# Python 3
import tkinter
import tkinter.scrolledtext as scrolledtext

root = tkinter.Tk()
# 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')

root.mainloop()

에게 두 새로운 종료을 제공합니다.
기존의 File → Exit(파일 ▁exit 종료) 및 버튼도 선택할 수 있습니다.

활동에 , Tkinter때 Tkinter 동에라따를활, 리특히고 Tkinter.after를 사용하여 이 합니다.destroy()프로토콜, 단추 등을 사용하더라도 이 활동("실행 중" 오류)을 종료하는 것이 아니라 방해합니다.거의 모든 경우에 가장 좋은 해결책은 깃발을 사용하는 것입니다. 어리석은 . (하지 않다고 :) 여기그대사방는예있다어니습가은리만석지확않하신지필고다그하요!) :)

from Tkinter import *

def close_window():
  global running
  running = False  # turn off while loop
  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() 

이렇게 하면 그래픽 작업이 제대로 종료됩니다.은 하만면됩다니확만 확인하면 됩니다.running적재적소에

x 단추의 기능을 변경하거나 닫을 수 없도록 하려면 이 작업을 수행합니다.

yourwindow.protocol("WM_DELETE_WINDOW", whatever)

그럼 "감정"이 무엇을 의미하는지 무시합니다.

def whatever():
    # Replace this with your own event for example:
    print("oi don't press that button")

또한 창을 닫을 때 다음과 같이 다시 호출할 수 있도록 만들 수 있습니다.

yourwindow.withdraw() 

창을 숨기지만 닫지는 않습니다.

yourwindow.deiconify()

그러면 창이 다시 표시됩니다.

이것을 제게 알려주신 아포스톨로스의 답변에 감사드립니다.여기 2019년 파이썬 3에 대한 훨씬 더 자세한 예가 있으며, 더 명확한 설명과 예제 코드가 있습니다.


는 사실에 주의하십시오.destroy()또는 사용자 정의 창 닫기 처리기가 전혀 없는 경우 사용자가 창을 닫을과 실행 인 모든 콜백이 즉시 삭제됩니다.

의 현재 활동에 이는현재 에▁using▁this다있습니,를 사용할 때 당신에게 나쁠 수.tkinter.after(콜백 가능).일부 데이터를 처리하고 디스크에 쓰는 콜백을 사용하고 있을 수 있습니다.이 경우 데이터 쓰기가 갑자기 중단되지 않고 완료되기를 원하는 것이 분명합니다.

그것을 위한 가장 좋은 해결책은 깃발을 사용하는 것입니다.사용자가 창 닫기를 요청하면 플래그로 표시한 다음 이에 대응합니다.

(참고: 저는 보통 GUI를 잘 캡슐화된 클래스와 별도의 작업자 스레드로 설계하고 "global"을 사용하지 않습니다(대신 클래스 인스턴스 변수를 사용합니다). 하지만 이것은 사용자가 창을 닫을 때 TK가 어떻게 당신의 주기적인 콜백을 갑자기 죽였는지 보여주는 단순하고 분해된 예입니다...)

from tkinter import *
import time

# Try setting this to False and look at the printed numbers (1 to 10)
# during the work-loop, if you close the window while the periodic_call
# worker is busy working (printing). It will abruptly end the numbers,
# and kill the periodic callback! That's why you should design most
# applications with a safe closing callback as described in this demo.
safe_closing = True

# ---------

busy_processing = False
close_requested = False

def close_window():
    global close_requested
    close_requested = True
    print("User requested close at:", time.time(), "Was busy processing:", busy_processing)

root = Tk()
if safe_closing:
    root.protocol("WM_DELETE_WINDOW", close_window)
lbl = Label(root)
lbl.pack()

def periodic_call():
    global busy_processing

    if not close_requested:
        busy_processing = True
        for i in range(10):
            print((i+1), "of 10")
            time.sleep(0.2)
            lbl["text"] = str(time.time()) # Will error if force-closed.
            root.update() # Force redrawing since we change label multiple times in a row.
        busy_processing = False
        root.after(500, periodic_call)
    else:
        print("Destroying GUI at:", time.time())
        try: # "destroy()" can throw, so you should wrap it like this.
            root.destroy()
        except:
            # NOTE: In most code, you'll wanna force a close here via
            # "exit" if the window failed to destroy. Just ensure that
            # you have no code after your `mainloop()` call (at the
            # bottom of this file), since the exit call will cause the
            # process to terminate immediately without running any more
            # code. Of course, you should NEVER have code after your
            # `mainloop()` call in well-designed code anyway...
            # exit(0)
            pass

root.after_idle(periodic_call)
root.mainloop()

이 코드는 당신에게 그것을 보여줄 것입니다.WM_DELETE_WINDOW핸들러는 사용자 지정 중에도 실행됩니다.periodic_call()업무/시간 중에 바쁩니다!

는 꽤 된 우리는꽤과것사을용다합니된장▁some▁pretty다▁exagger를 사용합니다..after()값: 500밀리초.이것은 정기적인 통화가 통화 중일 때 닫는 것과 그렇지 않을 때 닫는 것 사이의 차이를 쉽게 알 수 있도록 하기 위한 것입니다.숫자가 업데이트되는 동안 닫으면 다음과 같은 것을 볼 수 있습니다.WM_DELETE_WINDOW주기적인 호출 "처리 중인 중에 발생했습니다.사실입니다. 숫자가 일시 중지된 상태에서 닫으면(즉, 정기적인 콜백이 처리되지 않는 상태에서 닫힘) 종료가 "비지" 상태일 때 발생했음을 알 수 있습니다.

사용할는, 당신의 제사용서에실,서▁your제사에,.after()응답 GUI를 사용하려면 30-100밀리초 정도의 시간이 필요합니다.이는 TK의 기본 "마감 시 모든 작업을 즉시 중단"하는 행동으로부터 자신을 보호하는 방법을 이해하는 데 도움이 되는 데모일 뿐입니다.

을 만듭니다.WM_DELETE_WINDOW한 후 합니다..destroy()창이 안전할 때(앱이 모든 작업을 완료했을 때).

: 사할수있다습니도용▁ps를 할 수도 있습니다.WM_DELETE_WINDOW사용자에게 창을 닫을지 묻는 메시지를 표시합니다. 사용자가 아니오라고 대답하면 플래그를 설정하지 않습니다.아주 간단합니다.당신은 단지 메시지 상자를 보여줍니다.WM_DELETE_WINDOW사용자의 답변에 따라 플래그를 설정합니다.

tkinter 창을 닫으려면 destroy()를 사용해야 합니다.

   from Tkinter import *
   root = Tk()
   Button(root, text="Quit", command=root.destroy).pack()
   root.mainloop()

설명:

root.quit()위의 라인은 단지 다음을 우회합니다.root.mainloop()root.mainloop()됩니다.quit()명령이 실행됩니다.

root.destroy()하는 동안에destroy().root.mainloop()root.mainloop()정지합니다.

프로그램을 종료하고 싶으니 다음을 사용해야 합니다.root.destroy()그것이 메인 루프를 멈출 것이기 때문에.

하지만 무한 루프를 실행하고 싶고 TK 창을 파괴하고 싶지 않고 다음 이후에 코드를 실행하고 싶다면,root.mainloop()라인 그렇다면 당신은 사용해야 합니다.root.quit() 예:

from Tkinter import *
def quit():
    global root
    root.quit()

root = Tk()
while True:
    Button(root, text="Quit", command=quit).pack()
    root.mainloop()
    #do something

가장 쉬운 코드는 다음과 같습니다.

from tkinter import *
window = Tk()

경우: 숨기창:window.withdraw()

과 같이 하십시오.window.deiconify()

창서나가경우는에:exit()

창에서 나가는 경우(.exe 파일을 만든 경우):

from tkinter import *
import sys
window = Tk()
sys.exit()

그리고 물론 버튼을 배치하고 위의 코드를 함수에 사용해야 버튼의 명령 부분에 함수의 이름을 입력할 수 있습니다.

간단한 버전을 사용해 보십시오.

import tkinter

window = Tk()

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

window.mainloop()

또는 명령을 추가하려는 경우:

import tkinter

window = Tk()


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


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

window.mainloop()

사용할 수 있는 항목:

root = Tk()
def func():
    print('not clossed')
root.protocol('wm_delete_window', func)
root.mainloop()
def on_closing():
    if messagebox.askokcancel("Quit", "would you like to quit"):
        window.destroy()


window.protocol("WM_DELETE_WINDOW", on_closing)

이와 같은 창 닫기 이벤트를 처리할 수 있습니다. 다른 작업을 수행하려면 on_message 함수에서 발생하는 작업을 변경하십시오.

나는 훨씬 더 간단한 방법이 그것을 사용하는 것이라고 말합니다.break 예를 들어 , 예들어

import tkinter as tk
win=tk.Tk
def exit():
    break
btn= tk.Button(win, text="press to exit", command=exit)
win.mainloop()

사용 OR 용사sys.exit()

import tkinter as tk
import sys
win=tk.Tk
def exit():
    sys.exit
btn= tk.Button(win, text="press to exit", command=exit)
win.mainloop()

언급URL : https://stackoverflow.com/questions/111155/how-do-i-handle-the-window-close-event-in-tkinter

반응형