在Tkinter动画框架中设置背景图像

时间:2019-04-23 19:15:56

标签: python python-2.7 tkinter background lag

我目前正在为一个水果忍者项目上课。一切功能正常,但是,当我尝试放入游戏的背景图像时,运行速度非常慢。为了使游戏看起来更优美,我需要在具有游戏背景的同时使所有工作顺利进行。我遇到并试图理解的其他解决方案根本无法正常工作,或者文件永远不会运行。

仅供参考:我正在使用python 2.7。

我尝试了其他一些添加背景的建议,例如使用标签功能,但是,当我尝试实现它时,会遇到各种各样的错误,并且似乎在我的动画框架中不起作用。

def run(width=300, height=300):
    def redrawAllWrapper(canvas, data):
        canvas.delete(ALL)
        canvas.create_rectangle(0, 0, data.width, data.height,
                                fill='white', width=0)
        redrawAll(canvas, data)
        canvas.update()    

    def mousePressedWrapper(event, canvas, data):
        mousePressed(event, data)
        redrawAllWrapper(canvas, data)

    def keyPressedWrapper(event, canvas, data):
        keyPressed(event, data)
        redrawAllWrapper(canvas, data)

    def timerFiredWrapper(canvas, data):
        timerFired(data)
        redrawAllWrapper(canvas, data)
        # pause, then call timerFired again
        canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
    # Set up data and call init
    class Struct(object): pass
    data = Struct()
    data.width = width
    data.height = height
    data.timerDelay = 10 # milliseconds
    root = Tk()
    root.resizable(width=False, height=False) # prevents resizing window

    init(data)
    # create the root and the canvas
    canvas = Canvas(root, width=data.width, height=data.height)
    canvas.configure(bd=0, highlightthickness=0)
    canvas.pack()
    # set up events
    root.bind("<Button-1>", lambda event:
                            mousePressedWrapper(event, canvas, data))
    root.bind("<Key>", lambda event:
                            keyPressedWrapper(event, canvas, data))
    timerFiredWrapper(canvas, data)
    # and launch the app
    root.mainloop()  # blocks until window is closed
    print("bye!")

run(1200, 700)

在当前框架下,我在该运行函数上方的init,timerFired,redrawAll,keyPressed和mousePressed函数中编写了所有必需的代码。

以我当前的背景执行。我在1200 x 700 gif文件上使用PhotoImage,并在redrawAll函数(每10毫秒称为一次)中在整个屏幕上绘制图像。没有绘制该图像,我的游戏运行非常平稳,但是,在redrawAll中绘制图像时,游戏明显滞后,所以我知道滞后的原因是绘制背景图像。

这是在redrawAll中绘制它的代码行:

canvas.create_image(data.width // 2,data.height // 2,image = data.background)

这是否仅是因为我在redrawAll中执行此操作,每次调用该函数使其变慢时都会连续绘制图像?在Tkinter中只是拥有如此大的图像会使其变慢吗?来源是什么?

有一种方法可以简单地在背景上绘制一次图像,并且永远不会改变?还是有什么办法可以避免滞后?我只是觉得很奇怪。同样,这是在Mac上的python 2.7中。

谢谢!

1 个答案:

答案 0 :(得分:1)

您不必删除并再次添加所有元素即可刷新屏幕。您可以移动元素,画布可以正确绘制

此代码创建了1000个小矩形,并在背景上随机移动它们。

在Python 3.7上进行了测试,但在2.7上也应该可以工作。

使用5_000矩形会减慢速度,但效果仍然不错(但不是很完美)。使用10_000会减慢太多速度。

from Tkinter import *
from PIL import Image, ImageTk
import random

IMAGE_PATH = 'background.jpg'

class Struct(object):
    pass

def run(width=300, height=300):

    def init(data):
        # create 1000 rectangles in random position
        for _ in range(1000):
            x = random.randint(0, data.width)
            y = random.randint(0, data.height)
            data.data.append(canvas.create_rectangle(x, y, x+10, y+10, fill='red'))

    def mousePressedWrapper(event, canvas, data):
        #mousePressed(event, data)
        pass 

    def keyPressedWrapper(event, canvas, data):
        #keyPressed(event, data)
        pass

    def timerFiredWrapper(canvas, data):
        # move objects
        for rect_id in data.data:
            x = random.randint(-10, 10)
            y = random.randint(-10, 10)
            canvas.move(rect_id, x, y)

        # pause, then call timerFired again
        canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)

    # Set up data and call init
    data = Struct()
    data.width = width
    data.height = height
    data.timerDelay = 10 # milliseconds
    data.data = [] # place for small red rectangles

    root = Tk()
    root.resizable(width=False, height=False) # prevents resizing window

    # create the root and the canvas
    canvas = Canvas(root, width=data.width, height=data.height)
    canvas.configure(bd=0, highlightthickness=0)
    canvas.pack()

    #canvas.create_rectangle(0, 0, data.width, data.height, fill='white', width=0)
    img = Image.open(IMAGE_PATH)
    img = img.resize((data.width, data.height))
    photo = ImageTk.PhotoImage(img)
    canvas.create_image(0, 0, image=photo, anchor='nw')

    init(data) # init after creating canvas because it create rectangles on canvas

    # set up events
    root.bind("<Button-1>", lambda event:
                            mousePressedWrapper(event, canvas, data))
    root.bind("<Key>", lambda event:
                            keyPressedWrapper(event, canvas, data))
    timerFiredWrapper(canvas, data)

    # and launch the app
    root.mainloop()  # blocks until window is closed
    print("bye!")

run(1200, 700)
相关问题