2017-09-22 1 views
0

기본적으로 루프를 계속 실행하려고하는 프로그램의 끝에 while 루프를 추가 할 때까지 다음 코드가 제대로 작동합니다. 창을 닫을 때까지 영원히 (화면 업데이트). 기존 코드에 위의 코드를 추가하는 방법에 대한_tkinter.TclError : "업데이트"명령을 호출 할 수 없습니다. 응용 프로그램이 손상되었습니다. 오류

while 1: 
     tk.update_idletasks() 
     tk.update() 
     time.sleep(0.01) 

, 프로그램은 실행하지만 출구에 ...이 오류와 함께 제공 :이와 비슷한 질문을 본

_tkinter.TclError: can't invoke "update" command: application has been destroyed error 

SO에 대한 오류는 있지만이 특정 문제에 대한 답변은 없으며 어떤 답변도 내 구체적인 사례에 도움이되지 않습니다.

전체 코드는 다음과 같습니다 :

질문/문제 :이 오류를 일으키는 내가 그것을 어떻게 해결할 수 무엇?

from tkinter import * 
import random 
import time 
tk=Tk() 
tk.title("My 21st Century Pong Game") 
tk.resizable(0,0) 
tk.wm_attributes("-topmost",1) 
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0) 
canvas.pack() 
tk.update() 


class Ball: #create a ball class 
    def __init__(self,canvas,color): #initiliased with the variables/attributes self, canvas, and color 
     self.canvas=canvas #set the intiial values for the starting attributes 
     self.id=canvas.create_oval(30,30,50,50,fill=color) #starting default values for the ball 
     """ Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval 
     """ 
     self.canvas.move(self.id,0,0) #this moves the oval to the specified location 

    def draw(self): #we have created the draw method but it doesn't do anything yet. 
     pass 


ball1=Ball(canvas,'green') #here we are creating an object (green ball) of the class Ball 

while 1: 
    tk.update_idletasks() 
    tk.update() 
    time.sleep(0.01) 

설명 업데이트 : 그것은 또한 설명 할 가치가

:

메인 루프가 프로그램의 중심 부분이며, IDLE 이미 메인 루프를 가지고 -하지만 당신은이를 실행하는 경우 IDLE 외부에서 프로그램을 실행하면 캔버스가 나타나고 잠시 후에 사라집니다. 창을 닫지 않게하려면 애니메이션 루프가 필요합니다. 따라서 while 1 : ..... 그렇지 않으면 아래에 설명 된대로 잠시 기다릴 필요가 없습니다. IDLE에 이미이 위치가 있습니다 (1 : .. 등등을 사용하지 않고 IDLE에서 잘 작동 함)

+1

단지 고정 된 코드 들여 쓰기를 - 미안 – MissComputing

+0

사이드 참고 : Tkinter를 함께'절전()'와'대기()'사용하지 마십시오. 이러한 방법은 tkinter와 잘 작동하지 않습니다. 대신'after()'를 사용하십시오. –

답변

1

내가 여기에 mainloop()을 사용해야한다는 것에 동의하지만 원래 코드를 유지하려는 경우 부울을 추적하고 대신 while x == True을 수행합니다. 이 방법으로 우리는 x의 값을 False과 동일하게 업데이트 할 수 있으며 오류가 발생하지 않도록해야합니다.

protocol() 메서드를 사용하면 앱이 닫히면 부울을 업데이트 할 수 있습니다.

x = True 

def update_x(): 
    global x 
    x = False 

tk.protocol("WM_DELETE_WINDOW", update_x) 

을 그리고 당신의 while 문에 변경 :

우리가 코드에 이것을 추가하면

while x == True: 
    tk.update_idletasks() 
    tk.update() 
    time.sleep(0.01) 

를 따라서 당신의 전체 코드는 다음과 같습니다

from tkinter import * 
import random 
import time 


tk=Tk() 
tk.title("My 21st Century Pong Game") 
tk.resizable(0,0) 
tk.wm_attributes("-topmost",1) 

x = True 

def update_x(): 
    global x 
    x = False 

tk.protocol("WM_DELETE_WINDOW", update_x) 
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0) 
canvas.pack() 
tk.update() 

class Ball: 
    def __init__(self,canvas,color): 
     self.canvas=canvas 
     self.id=canvas.create_oval(30,30,50,50,fill=color) 
     """ Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval 
     """ 
     self.canvas.move(self.id,0,0) 

    def draw(self): 
     pass 

ball1=Ball(canvas,'green') 

while x == True: 
    tk.update_idletasks() 
    tk.update() 
    time.sleep(0.01) 

이를 문제를 해결할 것입니다.

다른 사람들이 실제로 필요한 모든 것을 반복하는 것은 while i: 문이 아니라 여기에 mainloop()입니다.

Tk() 인스턴스의 루프에서 재설정하는 데 mainloop() 메서드를 사용하면 코드가 tk.mainloop()이라는 줄에 도달하면 코드의 다음 루프가됩니다.

코드를 작성하는 올바른 방법은 mainloop()을 사용하여 tkinter 인스턴스의 모든 업데이트를 수행하는 것입니다.

mainloop()를 사용하여 코드를 아래 참조 :

from tkinter import * 

tk=Tk() 
tk.title("My 21st Century Pong Game") 
tk.resizable(0,0) 
tk.wm_attributes("-topmost",1) 

canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0) 
canvas.pack() 
tk.update() 

class Ball: 
    def __init__(self,canvas,color): 
     self.canvas=canvas 
     self.id=canvas.create_oval(30,30,50,50,fill=color) 
     """ Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval 
     """ 
     self.canvas.move(self.id,0,0) 

    def draw(self): 
     pass 

ball1=Ball(canvas,'green') 

tk.mainloop() 
+0

솔루션은 비효율적 인 코드 4 줄을 9 줄로 변환합니다. 올바른 해결책은 모든 코드를 한 줄의 코드로 대체하는 것입니다. –

+0

@BryanOakley 나는 나의 대답에서 가장 좋은 옵션은'mainloop()'을 사용하는 것이라고 말했듯이 나는 그것을 분명하게했다. 나는 오리지널 코드를 사용하기 위해 OP가 기능적으로 만 제공하고 있었기 때문에 그들이 잘못하고있는 것을 볼 수있었습니다. –

1

효과적으로 사용하는 대신 mainloop을 구현하려고합니다.

mainloop을 이해하려면 here에 대해 읽어보십시오. 추가 한 새 코드의 구문 론적 추상화라고 생각할 수 있습니다. 귀하의 while 루프. 당신은 이미 하나가 존재할 때 "화면을 업데이트"하기 위해 자신의 루프를 만들어서 휠을 재현하려고 거의 시도하고 있습니다!

프로그램을 종료 할 때 sys.exit()을 사용하면 오류를 피할 수 있습니다.

편집 :이

while 1: 
    tk.update_idletasks() 
    tk.update() 
    time.sleep(0.01) 

:

다음 코드를 교체

가 말한대로, 당신이 경우 창을 업데이트 할 수 없기 때문에 귀하의 오류가
tk.mainloop() 

파괴되었습니다. mainloop이 처리해야합니다.

+1

SneakyTurtle - 이것은 전혀 의미가 없습니다. 내가 필요로하는 코드를 게시 해 주실 수 있습니까? 이상적으로 upvote하고 싶습니다! :-) "while"을 tk.mainloop()으로 대체한다는 것은 무엇을 의미합니까? – MissComputing

+0

동의 - 명확하지 않거나 코드/답변을 게시 할 수없는 경우를 제외하고는 도움이되지 않습니다. 물론 하나는 빠져 나와 sys.exit()를 사용하지 않아도되지만 어떤 컨텍스트와 방법으로 사용할 수 있습니까? –

+0

@MissComputing @pythoncarrot, 나는 mainloop이 무엇인지 설명하기 위해 메인 포스트를 편집했다. – SneakyTurtle

1

응용 프로그램을 종료하면 다음 번에 update_idletasks으로 전화 할 때 창 개체가 소멸됩니다. 그런 다음 존재하지 않는 창에서 update으로 전화를 걸려고합니다.

while으로 시작하는 네 줄을 모두 제거하고 그 줄을 적절하게 처리하는 단일 줄 tk.mainloop()으로 바꾸어야합니다.

원본 코드를 유지하려는 경우 update_idletasksupdate을 호출 할 이유가 없습니다. 전자는 후자의 부분 집합입니다.

관련 문제