【问题标题】:Moving object on canvas python在画布 python 上移动对象
【发布时间】:2021-04-01 02:01:33
【问题描述】:

我想让一个小方块每 3 秒向左移动 10 个像素,我的代码如下。我不确定为什么它只移动一次。一些帮助将不胜感激!

import tkinter as tk
import time
 
root = tk.Tk()
 
WIDTH = HEIGHT = 400
 
x1 = y1 = WIDTH / 2
 
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
canvas.pack()
 
c1 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10)
c2 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10)
 
 
def draw_rect():
    global c2
    canvas.delete(c2)
    c2 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="green")
 
 
def del_rect():
    canvas.delete(c1)
    #canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="white", opacity=0.5)

while 1:
    root.update()
    time.sleep(3)
    del_rect()
    x1 -= 10    
    draw_rect()
    root.mainloop()

【问题讨论】:

  • 您能否详细说明“不起作用”的含义?
  • 实际上矩形被移动了(尽管它们不是同一个矩形),因为窗口上显示的最终矩形被绿色填充(初始矩形没有被填充)。如果您在time.sleep(3) 之前添加root.update(),您将看到移动。
  • 谢谢!在使用您的建议后,我设法看到它移动了一次。我希望看到它不断地移动。正如我在上面更新的那样,我将代码的底部 5 行放在 while 循环中,但它仍然只移动一次。
  • root.mainloop() 在窗口关闭之前不会返回。摆脱那条线。请注意,此方法的 GUI 不会非常响应,因为它会一次完全冻结 3 秒。您想改用.after() 来安排未来的活动。
  • canvas 具有 move() 功能 - 因此您不必删除矩形并重新创建它。

标签: python tkinter tkinter-canvas


【解决方案1】:

mainloop() 运行循环,直到你关闭窗口 - 所以它阻塞所有循环并且它只执行一次并且它只移动一次矩形。在您的版本中,您应该删除mainloop(),它不会阻止它 - 因为您在循环中使用update(),所以它会正确运行。

但你可以用不同的方式做到这一点。

你可以使用root.after(3000, draw_rect)在3秒后执行draw_rect()draw_rect() 应该再次运行 root.after(3000, draw_rect) 以在 3 秒后再次运行它 - 这样它将循环并且不会被 mainloop() 阻塞(mainloop() 将运行 draw_rect() 每 3 秒)

Canvas 具有函数move(object, dx, dy),因此您不必删除矩形并重新创建它。

我使用300ms 来更快地运行它。

import tkinter as tk

# --- constants --- (PEP8: UPPER_CASE_NAMES)

WIDTH = 400
HEIGHT = 400

# --- functions ---

def move_rect():
    canvas.move(c1, -10, 0)  # move left
    canvas.move(c2, 10, 0)   # move right
    
    # run again after 300ms
    root.after(300, move_rect)  # 300ms = 0.3s  # I use smaller value to make it faster

# --- main ---

x1 = y1 = WIDTH / 2
 
root = tk.Tk()

canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
canvas.pack()
 
c1 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="green")
c2 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="red")

# run first time after 300ms
root.after(300, move_rect)  # 300ms = 0.3s  # I use smaller value to make it faster
 
root.mainloop()

PEP 8 -- Style Guide for Python Code


编辑:

使用变量speed1speed2 在矩形靠近边界时改变方向的版本。

import tkinter as tk

# --- constants --- (PEP8: UPPER_CASE_NAMES)

WIDTH = 400
HEIGHT = 400

# --- functions ---

def move_rect():
    global speed1
    global speed2
    
    #x1, y1, x2, y2 = canvas.coords(c1)
    pos = canvas.coords(c1)
    if speed1 < 0 :
        if pos[0] < 10:
            speed1 = -speed1
    else:
        if pos[2] > WIDTH-10:
            speed1 = -speed1
        
    #x1, y1, x2, y2 = canvas.coords(c2)
    pos = canvas.coords(c2)
    if speed2 < 0:
        if pos[0] < 10:
           speed2 = -speed2
    else:
        if pos[2] > WIDTH-10:
            speed2 = -speed2
        
    canvas.move(c1, speed1, 0)  # move left    
    canvas.move(c2, speed2, 0)  # move right
    
    # run again after 30ms
    root.after(30, move_rect)  # 30ms = 0.03s  - I uses smaller value to make it faster

# --- main ---

x1 = y1 = WIDTH / 2

speed1 = -10
speed2 = +10

root = tk.Tk()

canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
canvas.pack()
 
print(dir(canvas)) 
c1 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="green")
c2 = canvas.create_rectangle(x1, y1, x1 + 10, y1 + 10, fill="red")

# run first time after 300ms
root.after(300, move_rect)  # 300ms = 0.3s  - I uses smaller value to make it faster
 
root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多