我尝试使用一个简单的程序来学习Python,该程序使用tkinter
生成正方形。
在画布上移动它们,然后再生成它们。
2个问题。
我该如何生成它们?我发现了有关canvas.destroy()
方法的信息,但还是没有执行任何操作,或者出现了超出范围的错误。
我创建了一个创建正方形并在其中具有移动功能的类。我通过按钮在类实例上调用move函数。 它正在工作,但现在我想一次调用它们,以便它们彼此独立移动。问题是,如果我单击按钮,对于实例Nº2,已经移动的正方形(实例Nº1)停止运行。 为什么?以及我该如何解决?
这里是我的代码,只有汽车课,我想其余的并不重要:(如果我愚蠢,请原谅我……我是新来的
import tkinter as tk
from tkinter import messagebox
import time
import random
root = tk.Tk()
root.title("Timer TrafficLight")
root.geometry("500x500")
# root.resizable(0,0)
canvas = tk.Canvas(root, width= 500, height= 500, bg="darkgray")
canvas.pack(anchor = "s")
class Street(object):
img_street_vertical = tk.PhotoImage(file="Street_vertical.gif")
img_street_horizontal = tk.PhotoImage(file="Street_horizontal.gif")
def __init__(self, x, y, alignment):
self.x = x
self.y = y
self.alignment = alignment
self.img = self.set_img()
self.street = canvas.create_image(self.x, self.y, image = self.img, anchor = "nw")
def set_img(self):
if self.alignment == "h":
return self.img_street_horizontal
elif self.alignment == "v":
return self.img_street_vertical
else:
print ("Please set the alingment to eigher h or v ")
.
.
.
class TrafficLight(object):
def __init__(self, rx1, ry1, rx2, ry2):
#Trafficlight outer lines
self.rx1 = rx1
self.ry1 = ry1
self.rx2 = rx2
self.ry2 = ry2
self.lines = canvas.create_rectangle(self.rx1, self.ry1, self.rx2, self.ry2)
#Light Bulbs
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "gray"
self.after_id = ""
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = "gray")
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = "gray")
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = "gray")
def set_off(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "gray"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_green(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "green"
self.total_state = "green"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_yellow(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "yellow"
self.under_state = "gray"
self.total_state = "yellow"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_red(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "red"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "red"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def timer(self):
red_timer = 50
yellow_timer = 40
green_timer = 50
if self.total_state == "gray":
self.set_red()
self.after_id = canvas.after(red_timer, self.timer)
elif self.total_state == "red":
self.set_green()
self.after_id = canvas.after(green_timer, self.timer)
elif self.total_state == "yellow":
self.set_red()
self.after_id = canvas.after(red_timer, self.timer)
elif self.total_state == "green":
self.set_yellow()
self.after_id = canvas.after(yellow_timer, self.timer)
else:
messagebox.showerror("Error", "Traffic Light had invalid Value Initialisation only allows Values: gray,red,yellow or green")
exit()
def stop_timer(self):
canvas.after_cancel(self.after_id)
def walk(self):
#need to include a "if" in case that state is "red" or "yellow" when the button is pressed.
self.stop_timer()
canvas.after(5000, self.set_yellow)
canvas.after(5000, self.set_red)
canvas.after(10000, self.timer)
class Car(object):
spawns = ["left", "right", "top", "buttom"]
xd = 0
yd = 0
def __init__(self):
self.spawnpoint = random.choice(self.spawns)
self.spawn_coords = self.spawn()
self.square = canvas.create_rectangle(self.spawn_coords[0], self.spawn_coords[1], self.spawn_coords[2], self.spawn_coords[3], fill="red", tags = "test")
self.coords = canvas.coords(self.square)
def spawn(self):
if self.spawnpoint == "left":
return [10,260,40,270]
elif self.spawnpoint == "right":
return [485,220,455,230]
elif self.spawnpoint == "top":
return [220,10,230,40]
elif self.spawnpoint == "buttom":
return [260,485,270,455]
else:
print ("invalid spawn Point")
exit()
def move(self):
while True:
if self.spawnpoint == "left":
self.xd = 5
self.yd = 0
if self.coords[2] + self.xd >= 500:
print ("Left reached")
return False
elif self.spawnpoint == "right":
self.xd = -5
self.yd = 0
if self.coords[0] + self.xd <= 0:
print ("Right reached")
return False
elif self.spawnpoint == "top":
self.xd = 0
self.yd = 5
if self.coords[3] + self.xd >= 500:
print ("top reached")
return False
elif self.spawnpoint == "buttom":
self.xd = 0
self.yd = -5
if self.coords[1] + self.xd <= 0:
print ("buttom reached")
return False
else:
print ("invalid spawn Point")
exit()
canvas.move(self.square, self.xd, self.yd)
self.coords = canvas.coords(self.square)
root.update()
# canvas.after(500, self.move)
time.sleep(.05)
#X1 = 0
#X2 = 2
#y1 = 1
#y2 = 3
#between x1 and x2 = 30 pixels
#between y and y2 = 65 pixels
l1 = TrafficLight(170, 140, 200, 205)
l2 = TrafficLight(300, 140, 330, 205)
l3 = TrafficLight(170, 295, 200, 360)
l4 = TrafficLight(300, 295, 330, 360)
s1= Street(0, 208, "v")
s2= Street(208, 0, "h")
c1= Car()
c2= Car()
c3= Car()
c4= Car()
m = Menus(root)
while True:
c1.move()
c2.move()
c3.move()
c4.move()
time.sleep(.05)
root.mainloop()
答案 0 :(得分:0)
有太多未连接的代码,并且一篇帖子的问题太多。
请避免在gui中使用time.sleep
,并且避免将while
与mainloop
一起使用
我不知道您为什么使用exit()
,但它可能没有达到您的预期。
避免使用root.update
,通常是不必要的。
您可能应该有一个独立于TimerControl
的类TrafficLights
;实际上TrafficLights
应该是TimerControl
的奴隶
您应提供使用的图像,以免成为运行代码的负担;同样,您的代码无法运行,需要修复后我们才能回答您的问题。
以下内容显示您的汽车驶向相反的边缘,然后停下来:
import tkinter as tk
from tkinter import messagebox
import time
import random
root = tk.Tk()
root.title("Timer Traffic-Light")
root.geometry("500x500")
canvas = tk.Canvas(root, width=500, height=500, bg="darkgray")
canvas.pack(anchor="s")
class Street(object):
img_street_vertical = tk.PhotoImage(file="Street_vertical.gif")
img_street_horizontal = tk.PhotoImage(file="Street_horizontal.gif")
def __init__(self, x, y, alignment):
self.x = x
self.y = y
self.alignment = alignment
self.img = self.set_img()
self.street = canvas.create_image(self.x, self.y, image=self.img, anchor="nw")
def set_img(self):
if self.alignment == "h":
return self.img_street_horizontal
elif self.alignment == "v":
return self.img_street_vertical
else:
print ("Please set the alingment to eigher h or v ")
class TrafficLight(object):
def __init__(self, rx1, ry1, rx2, ry2):
#Trafficlight outer lines
self.rx1 = rx1
self.ry1 = ry1
self.rx2 = rx2
self.ry2 = ry2
self.lines = canvas.create_rectangle(self.rx1, self.ry1, self.rx2, self.ry2)
#Light Bulbs
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "gray"
self.after_id = ""
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = "gray")
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = "gray")
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = "gray")
def set_off(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "gray"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_green(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "gray"
self.under_state = "green"
self.total_state = "green"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_yellow(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "gray"
self.middle_state = "yellow"
self.under_state = "gray"
self.total_state = "yellow"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def set_red(self):
canvas.delete(self.top_bulb)
canvas.delete(self.middle_bulb)
canvas.delete(self.under_bulb)
self.top_state = "red"
self.middle_state = "gray"
self.under_state = "gray"
self.total_state = "red"
self.top_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 5, self.rx1 + 25, self.ry1 + 20, fill = self.top_state)
self.middle_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 25, self.rx1 + 25, self.ry1 + 40, fill = self.middle_state)
self.under_bulb = canvas.create_oval(self.rx1 + 5, self.ry1 + 45, self.rx1 + 25, self.ry1 + 60, fill = self.under_state)
def timer(self):
red_timer = 50
yellow_timer = 40
green_timer = 50
if self.total_state == "gray":
self.set_red()
self.after_id = canvas.after(red_timer, self.timer)
elif self.total_state == "red":
self.set_green()
self.after_id = canvas.after(green_timer, self.timer)
elif self.total_state == "yellow":
self.set_red()
self.after_id = canvas.after(red_timer, self.timer)
elif self.total_state == "green":
self.set_yellow()
self.after_id = canvas.after(yellow_timer, self.timer)
else:
messagebox.showerror("Error", "Traffic Light had invalid Value Initialisation only allows Values: gray,red,yellow or green")
exit()
def stop_timer(self):
canvas.after_cancel(self.after_id)
def walk(self):
#need to include a "if" in case that state is "red" or "yellow" when the button is pressed.
self.stop_timer()
canvas.after(5000, self.set_yellow)
canvas.after(5000, self.set_red)
canvas.after(10000, self.timer)
class Car(object):
spawns = ["left", "right", "top", "buttom"]
xd = 0
yd = 0
def __init__(self):
self.spawnpoint = random.choice(self.spawns)
self.spawn_coords = self.spawn()
self.square = canvas.create_rectangle(self.spawn_coords[0], self.spawn_coords[1], self.spawn_coords[2], self.spawn_coords[3], fill="red", tags = "test")
self.coords = canvas.coords(self.square)
def spawn(self):
if self.spawnpoint == "left":
return [10,260,40,270]
elif self.spawnpoint == "right":
return [485,220,455,230]
elif self.spawnpoint == "top":
return [220,10,230,40]
elif self.spawnpoint == "buttom":
return [260,485,270,455]
else:
print ("invalid spawn Point")
exit()
def move(self):
if self.spawnpoint == "left":
self.xd = 5
self.yd = 0
if self.coords[2] + self.xd >= 500:
print ("Left reached")
return False
elif self.spawnpoint == "right":
self.xd = -5
self.yd = 0
if self.coords[0] + self.xd <= 0:
print ("Right reached")
return False
elif self.spawnpoint == "top":
self.xd = 0
self.yd = 5
if self.coords[3] + self.xd >= 500:
print ("top reached")
return False
elif self.spawnpoint == "buttom":
self.xd = 0
self.yd = -5
if self.coords[1] + self.xd <= 0:
print ("buttom reached")
return False
else:
print ("invalid spawn Point")
root.after_forget(self.move)
canvas.move(self.square, self.xd, self.yd)
self.coords = canvas.coords(self.square)
root.after(100, self.move)
l1 = TrafficLight(170, 140, 200, 205)
l2 = TrafficLight(300, 140, 330, 205)
l3 = TrafficLight(170, 295, 200, 360)
l4 = TrafficLight(300, 295, 330, 360)
s1= Street(0, 208, "v")
s2= Street(208, 0, "h")
c1= Car()
c2= Car()
c3= Car()
c4= Car()
def move_cars():
for car in [c1, c2, c3, c4]:
car.move()
move_cars()
root.mainloop()