2017-03-03 10 views
6

はTkinterの単純な移動を行うために試み:Y移動用のX移動のための1つ、およびもう: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) 

。しかし、矩形の実際の動きは実際には遅いです(1秒あたり約5回の動き)、self.window.master.after()の時間は効果がないようです。

これまでの別のtkinterプロジェクトでは、私は本当に反応したtkinterの動きを得ることができたので、私は、この場合、時間の更新を最小限に抑える方法があるかどうか、まったく異なるコードであってもよい。

更新:.after()メソッドの時刻は重要ですが、実際にはメソッドのリアルタイムにスタックされます。メソッドの呼び出し時にtimeitを使用した後、私はこの出力を得た:

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

だから私は、本当の問題があると思います:なぜそれ.after()方法はそう長く取っていますか?

更新2:複数のコンピュータでテストしたところ、いずれのプラットフォームでも動きはまだ遅いです。

+0

これはprobemを説明するために必要以上の方法より多くのコードのようになります。ここでは

は(わずかに)変更されたコードです。以下のアドバイスを読んで、それに従ってください:[最小限で完全で検証可能なサンプルを作成する方法](http://stackoverflow.com/help/mcve)、または質問をhttp://codereview.stackexchange.com/に移動してください –

+1

これを最小化しました。 – Dova

+0

「最小、完全、および検証可能」の「完全」部分を忘れてしまった。 –

答えて

1

少なくとも、Python 3.6を使用してWindows 10で報告した問題はありません。私は、プログラムを図のようにテストし、最後にroot.mainloop()を追加しなければならなかった。オブジェクトがキャンバスから離れすぎて見えなくなったため、これは長方形を示さなかった。

私はこれを壁の間で跳ね返し、カウンタを追加してmom_calcコール/秒を印刷しました。アフタータイムアウトを20msに設定すると、予想どおり、毎秒50回のモーションコールが発生します。これをあなたのポストのように2msに設定すると、毎秒約425回になるので、ここでは少しエラーがあり、1コールにつき約2.3または2.4msかかる。これは、他のプロセスがこの粒度で時間の一部を占める可能性があるため、少し変わります。

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 )Why are .NET timers limited to 15 ms resolution?を参照してください。

解決策は、Python - tkinter call to after is too slowで見つかりました。ここで、Andrew Medicoは(コメントで)うまく答えました。

関連する問題