2017-03-03 2 views
6

Tkinter가 간단한 동작을 수행하려고 시도는 Y 이동을위한 X 이동 하나, 다른 : self.momentum 2 개 정수를 포함하고있는 배열이고Tkinter에서이 모양이 왜 천천히 업데이트됩니까?

import tkinter as tk 

class GameApp(object): 
    """ 
    An object for the game window. 

    Attributes: 
     master: Main window tied to the application 
     canvas: The canvas of this window 
    """ 

    def __init__(self, master): 
     """ 
     Initialize the window and canvas of the game. 
     """ 

     self.master = master 
     self.master.title = "Game" 
     self.master.geometry('{}x{}'.format(500, 500)) 

     self.canvas = tk.Canvas(self.master) 
     self.canvas.pack(side="top", fill="both", expand=True) 

     self.start_game() 

    #----------------------------------------------# 


    def start_game(self): 
     """ 
     Actual loading of the game. 
     """ 

     player = Player(self) 

    #----------------------------------------------# 

#----------------------------------------------# 


class Player(object): 
    """ 
    The player of the game. 

    Attributes: 
     color: color of sprite (string) 
     dimensions: dimensions of the sprite (array) 
     canvas: the canvas of this sprite (object) 
     window: the actual game window object (object) 
     momentum: how fast the object is moving (array) 
    """ 


    def __init__(self, window): 

     self.color = "" 
     self.dimensions = [225, 225, 275, 275] 
     self.window = window 
     self.properties() 

    #----------------------------------------------# 

    def properties(self): 
     """ 
     Establish the properties of the player. 
     """ 

     self.color = "blue" 
     self.momentum = [5, 0] 

     self.draw() 
     self.mom_calc() 

    #----------------------------------------------# 

    def draw(self): 
     """ 
     Draw the sprite. 
     """ 

     self.sprite = self.window.canvas.create_rectangle(*self.dimensions, fill=self.color, outline=self.color) 

    #----------------------------------------------# 


    def mom_calc(self): 
     """ 
     Calculate the actual momentum of the thing 
     """ 

     self.window.canvas.move(self.sprite, *self.momentum) 
     self.window.master.after(2, self.mom_calc) 

    #----------------------------------------------# 

#----------------------------------------------# 


root = tk.Tk() 

game_window = GameApp(root) 

. 그러나 사각형의 실제 움직임은 실제로는 느립니다 (초당 약 5 회의 움직임). self.window.master.after() 시간은 효과가없는 것처럼 보입니다.

이전에 다른 tkinter 프로젝트에서 저는 정말 반응이 빠른 tkinter 움직임을 얻을 수있었습니다. 그래서이 경우에는 시간 이동 업데이트를 최소화 할 수있는 방법이 있는지 궁금 해서요. 다른 스타일의 OOP를 사용하거나, 또는 완전히 다른 코드 일 수 있습니다.

업데이트 : .after() 메서드의 시간은 중요하지만 실제로는 메서드의 실시간에 스택됩니다. 왜 .after() 방법이 너무 오래 걸리는 것을 :

>>> print(timeit.timeit("(self.window.master.after(2, self.mom_calc))", number=10000, globals={"self":self})) 
0.5395521819053108 

그래서 내가 진짜 문제는 추측 : 메서드를 호출 시간 timeit을 사용한 후,이 출력있어?

업데이트 2 : 여러 대의 컴퓨터에서 테스트되었는데, 어떤 플랫폼에서도 동작이 느립니다.

+0

이것은 probem을 설명하기 위해 필요한보다 훨씬 더 많은 코드처럼 보이는 : 여기

는 (약간) 수정 된 코드입니다. 아래의 조언을 읽고 따르십시오 : [최소한의 완전하고 검증 가능한 예제를 만드는 방법] (http://stackoverflow.com/help/mcve), 또는 질문을 http://codereview.stackexchange.com/으로 이동하십시오. –

+1

지금 최소화했습니다. – Dova

+0

"최소, 완료 및 확인 가능"의 "완료"부분을 잊어 버렸습니다. –

답변

1

Windows 10에서 적어도 Python 3.6을 사용하여보고 한 문제는 표시되지 않습니다. 나는 그 프로그램을 그림과 같이 시험했고 마지막에 root.mainloop()을 추가해야했다. 오브젝트가 캔버스에서 너무 빨리 벗어나서 사각형을 볼 수 없었습니다.

그래서 벽 사이를 바운스하고 카운터를 추가하여 초당 mom_calc 통화를 인쇄했습니다. after timeout을 20ms로 설정하면 예상대로 초당 50 모션 콜을 얻을 수 있습니다. 이 게시물을 2ms로 설정하면 약 초당 425 개가 발생하므로 여기에 약간의 오류가 있으며 통화 당 약 2.3 또는 2.4 밀리 초가 걸립니다. 이 프로세스는 다른 프로세스가이 세분성으로 시간의 일부를 차지할 수 있기 때문에 다소 가변적입니다.

import tkinter as tk 

class GameApp(object): 
    """ 
    An object for the game window. 

    Attributes: 
     master: Main window tied to the application 
     canvas: The canvas of this window 
    """ 

    def __init__(self, master): 
     """ 
     Initialize the window and canvas of the game. 
     """ 

     self.master = master 
     self.master.title = "Game" 
     self.master.geometry('{}x{}'.format(500, 500)) 

     self.canvas = tk.Canvas(self.master, background="white") 
     self.canvas.pack(side="top", fill="both", expand=True) 

     self.start_game() 

    #----------------------------------------------# 


    def start_game(self): 
     """ 
     Actual loading of the game. 
     """ 

     player = Player(self) 

    #----------------------------------------------# 

#----------------------------------------------# 


class Player(object): 
    """ 
    The player of the game. 

    Attributes: 
     color: color of sprite (string) 
     dimensions: dimensions of the sprite (array) 
     canvas: the canvas of this sprite (object) 
     window: the actual game window object (object) 
     momentum: how fast the object is moving (array) 
    """ 


    def __init__(self, window): 

     self.color = "" 
     self.dimensions = [225, 225, 275, 275] 
     self.window = window 
     self.movement = 0 
     self.movement_last = 0 
     self.properties() 

    #----------------------------------------------# 

    def properties(self): 
     """ 
     Establish the properties of the player. 
     """ 

     self.color = "blue" 
     self.momentum = [5, 0] 

     self.draw() 
     self.mom_calc() 
     self.velocity() 

    #----------------------------------------------# 

    def draw(self): 
     """ 
     Draw the sprite. 
     """ 

     self.sprite = self.window.canvas.create_rectangle(*self.dimensions, fill=self.color, outline=self.color) 

    #----------------------------------------------# 


    def mom_calc(self): 
     """ 
     Calculate the actual momentum of the thing 
     """ 

     pos = self.window.canvas.coords(self.sprite) 
     if pos[2] > 500: 
      self.momentum = [-5, 0] 
     elif pos[0] < 2: 
      self.momentum = [5, 0] 

     self.window.canvas.move(self.sprite, *self.momentum) 
     self.window.master.after(2, self.mom_calc) 
     self.movement = self.movement + 1 

    def velocity(self): 
     print(self.movement - self.movement_last) 
     self.movement_last = self.movement 
     self.aid_velocity = self.window.master.after(1000, self.velocity) 

    #----------------------------------------------# 

#----------------------------------------------# 


if __name__ == '__main__': 
    root = tk.Tk() 
    game_window = GameApp(root) 
    root.mainloop() 
+0

'root.mainloop ()'잊어 버린 바보처럼 느껴지세요. 감사. – Dova

3

"기본 Windows 타이머 해상도는 ~ 15ms입니다 .1ms마다 타이머를 작동시키는 것이 원하는대로 작동하지 않을 수 있으며 게임에 대한 필요성은 매우 낮습니다 (60FPS 업데이트가 16ms마다 실행되는 디스플레이는 ~ 16ms마다) Why are .NET timers limited to 15 ms resolution? "

Python - tkinter call to after is too slow에서 해답을 찾았습니다. Andrew Medico는 좋은 답변을했습니다 (의견에서).

관련 문제