首页 > 解决方案 > Tkinter 线程使用键盘事件为两组对象设置动画

问题描述

我正在设计一个类似于水果忍者的游戏的主要游戏区域。我试图让激光动画效果在他用户按下时显示,spacebar但一旦玩家放开它就会消失。

基本上,激光只会在用户按住空格键时出现。水果会被破坏,而分数会加分。但现在我只是在研究激光效果。该create_fruit()函数和move_fruit()函数旨在使水果随机生成并落在屏幕上。他们在没有激光动画的情况下工作得非常顺利。但是一旦添加了激光动画,整个东西就变得非常长,激光只会动画大约 0.5 秒然后冻结。

我试图将它添加到不同的线程,但结果是相同的。错误信息:RuntimeError: main thread is not in main loop。此外,由于极其滞后的效果和运行时错误,键盘事件基本上根本不起作用。

这是我的代码:

from tkinter import *
import time
from random import randint
from PIL import Image, ImageTk
from threading import *

#make the fruits appear on the screen
def create_fruits():
    
    global fruits_list

    #choose random fruits with different possibilities
    which_fruit = randint(1,10)

    this_fruit = ImageTk.PhotoImage(Image.open(fruit_dic[which_fruit]))
    #randomly generate which colum (four in total) the fruits will be
    choose_position = randint (1,4)
    
    x_position = x_positions_dic[choose_position]  # choose the position from dict

    my_photo = canvas.create_image(x_position, 80, image = this_fruit, anchor = 's')

    #append it to the list(image_if, x position, image)
    fruits_list.append([my_photo, randint(5,10), this_fruit])

    #repeatedly generate fruit images every 0.25 second (change the density of the fruit)
    root.after(250,create_fruits)
    

def move_fruits():
    #iterate through the fruit list
    for fruit in fruits_list:
        #call the move function, move the fruit
        canvas.move(fruit[0], 0, fruit[1])
        #if the fruit gets outside of the canvas, delete it on the canvas and in the list
        if canvas.bbox(fruit[0])[3] >= canvas.winfo_height()+200:
            canvas.delete(fruit[0])
            fruits_list.remove(fruit)

    root.after(5, move_fruits)  # calls the move_fruits after every 5 seconds (change the speed of the fruit)


def laser_threading(event = None):
    # Call work function
    t1=Thread(target=laser)
    t1.start()
    

def laser():
    # create a list of image objects
    for imagefile in laser_list:
        global laser_photo
        laser_photo = PhotoImage(file=imagefile)
        laser_giflist.append(laser_photo)

    # loop through the gif image objects for a while
    for k in range(0, 1000):
        for gif in laser_giflist:
            #place each frame on the canvas
            canvas.create_image(400, 600, image=gif)
            canvas.update()
            time.sleep(0.1)
            

#create game area
root = Tk ()

canvas = Canvas (root, height = 1200, width = 800, bg = 'black')
canvas.pack()

fruits_list = []

laser_list = ["laser_1.png","laser_2.png","laser_3.png",
             "laser_4.png"]

laser_giflist = []

x_positions_dic = {1: 160, 2: 287.5, 3: 462.5, 4:637.5}
fruit_dic = {
    1: r"bomb.png" ,
    2: r"apple.png" ,
    3: r"pear.png",
    4: r"blueberry.png",
    5: r"banana.png",
    6: r"cherry.png",
    7: r"mango.png",
    8: r"lemon.png",
    9: r"watermelon.png",
    10: r"bomb.png",
    } # images path 

create_fruits()
move_fruits()

root.bind("<space>", laser_threading)

mainloop()

标签: pythonpython-3.xtkintertkinter-canvastkinter-layout

解决方案


推荐阅读