拧入Tkinter以防止主回路冻结

2024-03-28 19:42:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Tkinter用画布做一个射击游戏。用户控制一个sprite,该sprite沿着x轴的方向不断地发射子弹。你知道吗

我遇到了一个问题,而试图动画子弹在屏幕上移动。我使用while True循环来保持项目符号连续移动,但是这会导致程序冻结。你知道吗

从我的研究中我了解到,我可能不得不使用线程来阻止主桌面冻结,但我还没有找到任何易于遵循的线程在Tkinter在线指南。你知道吗

这是我的密码:

from Tkinter import *
from Tkinter import Canvas
import time

window1 = Tk()
window1.title("Shoot 'Em Up")
window1.config(background="black")
window1.geometry("600x300")


def move_spryte1_up(event):
    xspeed = 0
    yspeed = -10
    canvas.move(spryte1, xspeed, yspeed)
    Tk.update(window1)


def move_spryte1_down(event):
    xspeed = 0
    yspeed = 10
    canvas.move(spryte1, xspeed, yspeed)
    Tk.update(window1)


def move_spryte1_left(event):
    xspeed = -10
    yspeed = 0
    canvas.move(spryte1, xspeed, yspeed)
    Tk.update(window1)


def move_spryte1_right(event):
    xspeed = 10
    yspeed = 0
    canvas.move(spryte1, xspeed, yspeed)
    Tk.update(window1)


def bullets():
    spryte1_pos = canvas.bbox(spryte1)
    newpos1 = spryte1_pos[1]
    newpos2 = spryte1_pos[2]-30
    newpos3 = spryte1_pos[3]-20
    spryte2 = canvas.create_rectangle(newpos1, newpos2, newpos3, newpos3, fill="blue")
    print(spryte1_pos)
    print(newpos1)
    print(newpos2)
    print(newpos3)
    while True:
        canvas.move(spryte2, 10, 0)
        Tk.update(window1)
        time.sleep(0.1)


canvas = Canvas(window1, width=600, height=300, bg="black", bd=0, highlightthickness=1, relief="ridge", highlightbackground="black")
canvas.pack()
points = [20, 40, 35, 40, 35, 30, 50, 40, 65, 40, 80, 52.5, 65, 65, 50, 65, 35, 75, 35, 65, 20, 65, 30, 62, 20, 59, 30, 56, 20, 53, 30, 50, 20, 47, 30, 44]
spryte1 = canvas.create_polygon(points, outline='red', fill='gray')
bullets()
canvas.tag_raise(spryte1)
window1.bind('<Up>', move_spryte1_up)
window1.bind('<Down>', move_spryte1_down)
window1.bind('<Left>', move_spryte1_left)
window1.bind('<Right>', move_spryte1_right)

window1.mainloop()

任何帮助都将不胜感激!你知道吗

编辑:这个问题与python - While Loop causes entire program to crash in Tkinter 略有不同,因为这是我最初在tkinter中寻找线程帮助时提出的问题。然而,我尝试了提出的解决方案,但发现它没有解决我的问题


Tags: poseventmovebindtkinterdefupdatetk
1条回答
网友
1楼 · 发布于 2024-03-28 19:42:16

对于这样简单的事情,你不需要线程,也不需要while循环。你知道吗

已经有一个无限循环运行事件循环(例如:mainloop)。您可以使用after方法对将来要执行的事件队列进行处理。要执行动画,只需调用函数来绘制一帧,然后让该函数将自身添加回事件队列以绘制下一帧。你知道吗

下面是对代码的简单修改,以说明这一点:

def bullets():
    spryte1_pos = canvas.bbox(spryte1)
    newpos1 = spryte1_pos[1]
    newpos2 = spryte1_pos[2]-30
    newpos3 = spryte1_pos[3]-20
    spryte2 = canvas.create_rectangle(newpos1, newpos2, newpos3, newpos3, fill="blue")
    shoot(spryte2, 10, 0)

def shoot(spryte, x, y):
    canvas.move(spryte, x, y)
    x0,y0,x1,y1 = canvas.bbox(spryte)
    if x0 < 600
        # call again in 100ms, unless the bullet is off the screen
        canvas.after(100, shoot, spryte, x, y)

画布可能可以在陷入困境之前处理几十个这样移动的存储过程。你知道吗

顺便说一句,您还可以删除move函数中对Tk.update(window1)的所有调用,这会增加开销并降低程序速度。一般来说,你应该从不打电话给update。你知道吗

相关问题 更多 >