我正在使用tkinter
创建道奇的副本。我在定时对象移动方面面临问题。有人告诉我时间模块不能与tkinter
一起正常工作,因此我应该改用after()
。但是,我在after()
函数中遇到的问题与在时间模块中一样。这是我的代码:
from tkinter import *
from random import randint
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.initWindow()
def initWindow(self):
self.master.title('Dodger')
self.pack(fill=BOTH, expand=1)
self.master.geometry('600x800')
self.master.config(bg='black')
menu = Menu(self.master)
self.master.config(menu=menu)
def clientExit():
exit()
file = Menu(menu)
file.add_command(label='Exit', command=clientExit)
file.add_command(label='Start', command=self.game)
menu.add_cascade(label='File', menu=file)
def game(self):
canvas = Canvas(self.master, width='600', height='800', borderwidth='0', highlightthickness='0')
canvas.pack()
canvas.create_rectangle(0, 0, 600, 800, fill='black', outline='black')
character = canvas.create_rectangle(270, 730, 330, 760, fill='magenta', outline='cyan', width='2')
def left(event):
cord = canvas.coords(character)
if cord[0] <= 5:
pass
else:
canvas.move(character, -10, 0)
def right(event):
cord = canvas.coords(character)
if cord[2] >= 595:
pass
else:
canvas.move(character, 10, 0)
self.master.bind('<Left>', left)
self.master.bind('<Right>', right)
class variables:
sizeMin = 10
sizeMax = 80
y = 10
minX = 5
maxX = 545
def createShape():
size = randint(variables.sizeMin, variables.sizeMax)
x = randint(variables.minX, variables.maxX)
topLeft = [x, variables.y]
bottomRight = [x + size, variables.y + size]
shape = canvas.create_rectangle(topLeft[0], topLeft[1], bottomRight[0], bottomRight[1],
fill='red', outline='red')
return shape
def moveShape(shape):
canvas.move(shape, 0, 800)
for x in range(5):
x = createShape()
self.master.after(1000, moveShape(x))
root = Tk()
app = Window(root)
app.mainloop()
如您所见,在游戏实例的底部,我创建了一个正方形并将其每隔1秒向下移动五次。但是,这没有用;我的窗户冻结了规定的时间,然后又恢复了。我不确定这是因为我的计算机故障还是做错了什么。请在您的编辑器中运行我的代码,并告诉我是否做错了事。
答案 0 :(得分:1)
冻结的原因是因为您打错after
。
考虑以下代码:
self.master.after(1000, moveShape(x))
...它与以下代码完全相同:
result = moveShape(x)
self.master.after(1000, result)
...与此相同,因为moveShape
返回None
:
result = moveShape(x)
self.master.after(1000, None)
...与此相同:
result = moveShape(x)
self.master.after(1000)
...与
相同result = moveShape(x)
time.sleep(1)
换句话说,您要告诉它睡觉,所以它就睡觉了。
after
需要函数的可调用或引用。您可以将其他args作为参数传递给after。因此,正确的调用方法是:
self.master.after(1000, moveShape, x)
但是,我怀疑这正是您想要的,因为所有五个迭代都将在循环开始后1000ms而不是相隔1000ms的时候尝试运行代码。只需简单地应用一些数学即可。
答案 1 :(得分:0)
您需要将sleep
函数替换为,并用after
循环。试试这个:
def moveShape():
if self.step < 5:
canvas.move(shape, 0, 10)
self.master.after(1000, moveShape)
self.step += 1
self.step = 0
shape = createShape()
moveShape()
此外,如果将其移动800像素,则在第一个刻度后便看不到它,因此我将移动量减少到10像素。
编辑:此操作以及许多其他错误修正和改进:
import tkinter as tk
from random import randint
class variables:
sizeMin = 10
sizeMax = 80
y = 10
minX = 5
maxX = 545
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.master = master
self.initWindow()
def initWindow(self):
self.master.title('Dodger')
self.pack(fill=tk.BOTH, expand=1)
self.master.geometry('600x800')
self.master.config(bg='black')
menu = tk.Menu(self.master)
self.master.config(menu=menu)
file = tk.Menu(menu)
file.add_command(label='Exit', command=self.quit)
file.add_command(label='Start', command=self.game)
menu.add_cascade(label='File', menu=file)
def game(self):
self.canvas = tk.Canvas(self.master, width='600', height='800', borderwidth='0', highlightthickness='0')
self.canvas.pack()
self.canvas.create_rectangle(0, 0, 600, 800, fill='black', outline='black')
self.character = self.canvas.create_rectangle(270, 730, 330, 760, fill='magenta', outline='cyan', width='2')
self.createShape()
self.moveShape() # start the moving
self.master.bind('<Left>', self.left)
self.master.bind('<Right>', self.right)
def left(self, event):
cord = self.canvas.coords(self.character)
if cord[0] <= 5:
pass
else:
self.canvas.move(self.character, -10, 0)
def right(self, event):
cord = self.canvas.coords(self.character)
if cord[2] >= 595:
pass
else:
self.canvas.move(self.character, 10, 0)
def createShape(self):
size = randint(variables.sizeMin, variables.sizeMax)
x = randint(variables.minX, variables.maxX)
topLeft = [x, variables.y]
bottomRight = [x + size, variables.y + size]
self.shape = self.canvas.create_rectangle(topLeft[0], topLeft[1], bottomRight[0], bottomRight[1],
fill='red', outline='red')
def moveShape(self, x=0):
if x < 5: # loop 5 times
self.canvas.move(self.shape, 0, 10)
self.after(1000, self.moveShape, x+1) # run this method again in 1,000 ms
root = tk.Tk()
app = Window(root)
app.mainloop()