Tkinter画布动画闪烁

时间:2016-07-28 09:38:22

标签: python tkinter tkinter-canvas

我用Tkinter写了一个Python程序,让球在屏幕上反弹。除了一个问题外,它的效果很好:当球移动时,球的最外边缘会闪烁。

我知道Tkinter自动进行双重缓冲,所以我认为我不应该有撕裂问题。我不确定错误来自哪里。关于如何摆脱它的任何想法?

代码如下。以下是它的要点:类Ball扩展Tk并在程序运行时创建。它设置游戏,将其封装在GModel中。然后GModel使用run()运行游戏,只是反复循环,调用update()。

import threading
from time import sleep, clock
from tkinter import *
from tkinter import ttk

SPEED = 150  # Pixels per second
WIDTH = 400
HEIGHT = 500
RAD = 25
PAUSE = 0  # Time added between frames.  Slows things down if necessary

class GModel:
    # Contains the game data.

    def __init__(self, can):
        # can is Canvas to draw on
        self.can = can
        self.circ = can.create_oval(0,0, 2*RAD, 2*RAD)

        # Position and velocity of the ball
        self.x, self.y = RAD, RAD
        self.dx, self.dy = SPEED, SPEED

        # Ball is moving?
        self.is_running = True

    def update(self, elapsed_time):
        # Updates the dynamic game variables.  elapsed_time is in seconds.
        change_x = self.dx * elapsed_time
        change_y = self.dy * elapsed_time

        self.can.move(self.circ, change_x, change_y)
        self.x += change_x
        self.y += change_y

        self.resolve_collisions()

    def resolve_collisions(self):
        # If the ball goes off the edge, put it back and reverse velocity
        if self.x - RAD < 0:
            self.x = RAD
            self.dx = SPEED
        elif self.x + RAD > WIDTH:
            self.x = WIDTH - RAD
            self.dx = -SPEED

        if self.y - RAD < 0:
            self.y = RAD
            self.dy = SPEED
        elif self.y + RAD > HEIGHT:
            self.y = HEIGHT - RAD
            self.dy = -SPEED

    def end_game(self):
        self.is_running = False

    def run(self):
        last_time = 0.0

        while self.is_running:
            # Get number of seconds since last iteration of this loop
            this_time = clock()
            elapsed_time = this_time - last_time
            last_time = this_time

            try:   # Use this here in case the window gets X'd while t still runs
                self.update(elapsed_time)
            except:
                self.is_running = False

            if (PAUSE > 0):
                sleep(PAUSE)  # Slow things down if necessary

class Ball(Tk):
    def __init__(self):
        Tk.__init__(self)

        self.can = Canvas(self, width=WIDTH, height=HEIGHT)
        self.can.grid(row=0, column=0, sticky=(N, W, E, S))
        self.gm = GModel(self.can)

    def mainloop(self):
        t = threading.Thread(target=self.gm.run, daemon=True)
        t.start()
        Tk.mainloop(self)

def main():
    Ball().mainloop()

if __name__ == "__main__":
    main()

0 个答案:

没有答案