【问题标题】:Automatically Moving Shape? Python 3.5 Tkinter自动移动形状? Python 3.5 Tkinter
【发布时间】:2017-01-21 10:59:32
【问题描述】:

在 python 中,我目前正在使用 tkinter 制作一个“游戏”,但它决定不工作。我想要做的是让一个矩形由鼠标移动,另一个矩形在玩家不做任何事情的情况下连续上下移动。这是我的代码:

from tkinter import *
import time
root = Tk()
root.title("Game")
root.geometry("800x800")

def motion():
    canvas.delete(ALL)
    a = canvas.create_rectangle(event.x-50, event.y-50, event.x+50, event.y+50, fill='red')

def motion2():
    b = canvas.create_rectangle(10, 100, 100, 10, fill='blue')
    y = -15
    x = 0
    time.sleep(0.025)
    canvas.move(b, x, -y)
    canvas.update()

canvas = Canvas(root, width=1000, height=5000, bg='white')
canvas.bind("<Motion>", motion)
canvas.pack(pady=0)

mainloop()

我希望这可以尽快解决。过去几天我一直在研究这个问题,但仍然没有答案。谢谢你的时间:) -杰克

【问题讨论】:

  • 使用root.after(milliseconds, function_name) 自动移动对象 - 并删除time.sleep()
  • 要移动对象,您不必删除对象并再次创建 - 您有 canvas.coords(object_id, ...)canvas.move(object_id, ...)。更好地阅读文档:即。 effbot.org/tkinterbook/canvas.htm

标签: python canvas tkinter


【解决方案1】:

您可以使用root.after(milliseconds, function_name)定期运行函数,它可以使用canvas.move(object_id, offset_x, offset_y)自动移动对象。

您可以使用canvas.coords(object_id, x1, y1, x2, y2) 使用鼠标位置设置新位置。 bind 使用一个参数(对象 event)执行函数,因此函数必须接收此参数。

import tkinter as tk

# --- functions ---

def move_a(event):
    canvas.coords(a, event.x-50, event.y-50, event.x+50, event.y+50)

def move_b():
    canvas.move(b, 1, 0)
    # move again after 25ms (0.025s)
    root.after(25, move_b)

# --- main ---

# init
root = tk.Tk()

# create canvas
canvas = tk.Canvas(root)
canvas.pack()

# create objects
a = canvas.create_rectangle(0, 0, 100, 100, fill='red')
b = canvas.create_rectangle(0, 0, 100, 100, fill='blue')

# start moving `a` with mouse
canvas.bind("<Motion>", move_a)

# start moving `b` automatically
move_b()

# start program
root.mainloop()

编辑:要上下移动,您必须使用带有speed 的变量,这样您就可以将其从speed 更改为-speed,然后再更改为speed。您还可以使用move_down = True/False 来检查当前方向(或者您可以使用speed 来检查方向,但b_move_down 对人们来说更具可读性)

import tkinter as tk

# --- functions ---

def move_a(event):
    canvas.coords(a, event.x-50, event.y-50, event.x+50, event.y+50)

def move_b():
    # inform function to use external/global variable 
    # because we use `=` to change its value
    global b_speed
    global b_move_down

    canvas.move(b, 0, b_speed)

    # get current position        
    x1, y1, x2, y2 = canvas.coords(b)

    # check if you have to change direction
    #if b_speed > 0:
    if b_move_down:
        # if it reachs bottom
        if y2 > 300:
            # change direction
            #b_move_down = False
            b_move_down = not b_move_down
            b_speed = -b_speed
    else:
        # if it reachs top
        if y1 < 0:
            # change direction
            #b_move_down = True
            b_move_down = not b_move_down
            b_speed = -b_speed

    # move again after 25 ms (0.025s)
    root.after(25, move_b)

# --- main ---

# init
root = tk.Tk()

# create canvas
canvas = tk.Canvas(root, width=500, height=300)
canvas.pack()

# create objects
a = canvas.create_rectangle(0, 0, 100, 100, fill='red')
b = canvas.create_rectangle(0, 0, 100, 100, fill='blue')
# create global variables
b_move_down = True
b_speed = 5

# start moving `a` with mouse
canvas.bind("<Motion>", move_a)

# start moving `b` automatically
move_b()

# start program
root.mainloop()

编辑:在画布上移动

import tkinter as tk

# --- functions ---

def move_a(event):
    canvas.coords(a, event.x-50, event.y-50, event.x+50, event.y+50)

def move_b():
    # inform function to use external/global variable 
    # because we use `=` to change its value
    global b_speed_x
    global b_speed_y
    global b_direction

    canvas.move(b, b_speed_x, b_speed_y)

    # get current position        
    x1, y1, x2, y2 = canvas.coords(b)

    if b_direction == 'down':
        if y2 >= 300:
            b_direction = 'right'
            b_speed_x = 5
            b_speed_y = 0
    elif b_direction == 'up':
        if y1 <= 0:
            b_direction = 'left'
            b_speed_x = -5
            b_speed_y = 0
    elif b_direction == 'right':
        if x2 >= 500:
            b_direction = 'up'
            b_speed_x = 0
            b_speed_y = -5
    elif b_direction == 'left':
        if x1 <= 0:
            b_direction = 'down'
            b_speed_x = 0
            b_speed_y = 5

    # move again after 25 ms (0.025s)
    root.after(25, move_b)

# --- main ---

# init
root = tk.Tk()

# create canvas
canvas = tk.Canvas(root, width=500, height=300)
canvas.pack()

# create objects
a = canvas.create_rectangle(0, 0, 100, 100, fill='red')
b = canvas.create_rectangle(0, 0, 100, 100, fill='blue')
# create global variables
b_direction = 'down'
b_speed_x = 0
b_speed_y = 5

# start moving `a` with mouse
canvas.bind("<Motion>", move_a)

# start moving `b` automatically
move_b()

# start program
root.mainloop()

编辑:最后一个例子 - 键 p 暂停游戏

#!/usr/bin/env python3

import tkinter as tk

# --- constants --- (UPPER_CASE names)

DISPLAY_WIDHT = 800
DISPLAY_HEIGHT = 600

# --- classes --- (CamelCase names)

#class Player():
#    pass

#class BlueEnemy():
#    pass

# --- functions --- (lower_case names)

def move_a(event):
    # don't move if gama paused
    if not game_paused:
        canvas.coords(a, event.x-50, event.y-50, event.x+50, event.y+50)

def move_b():
    # inform function to use external/global variable
    # because we use `=` to change its value
    global b_speed_x
    global b_speed_y
    global b_direction

    # don't move if gama paused
    if not game_paused:
        canvas.move(b, b_speed_x, b_speed_y)

        # get current position
        x1, y1, x2, y2 = canvas.coords(b)

        if b_direction == 'down':
            if y2 >= DISPLAY_HEIGHT:
                b_direction = 'right'
                b_speed_x = 5
                b_speed_y = 0
        elif b_direction == 'up':
            if y1 <= 0:
                b_direction = 'left'
                b_speed_x = -5
                b_speed_y = 0
        elif b_direction == 'right':
            if x2 >= DISPLAY_WIDHT:
                b_direction = 'up'
                b_speed_x = 0
                b_speed_y = -5
        elif b_direction == 'left':
            if x1 <= 0:
                b_direction = 'down'
                b_speed_x = 0
                b_speed_y = 5

    # move again after 25 ms (0.025s)
    root.after(25, move_b)

def pause(event):
    global game_paused

    # change True/False
    game_paused = not game_paused

    if game_paused:
        # center text on canvas
        canvas.coords(text_pause, DISPLAY_WIDHT//2, DISPLAY_HEIGHT//2)
    else:
        # move text somewhere outside canvas
        canvas.coords(text_pause, -1000, -1000)

# --- main --- (lower_case names)

# init
root = tk.Tk()

# key `p` pause game
game_paused = False
root.bind('p', pause)

# create canvas
canvas = tk.Canvas(root, width=DISPLAY_WIDHT, height=DISPLAY_HEIGHT)
canvas.pack()

# create objects
a = canvas.create_rectangle(0, 0, 100, 100, fill='red')
b = canvas.create_rectangle(0, 0, 100, 100, fill='blue')
# create global variables
b_direction = 'down'
b_speed_x = 0
b_speed_y = 5

# start moving `a` with mouse
canvas.bind("<Motion>", move_a)

# start moving `b` automatically
move_b()

# create text somewhere outside canvas - so it will be "invisible"
text_pause = canvas.create_text(-1000, -1000, text="PAUSED", font=(50,))

# start program
root.mainloop()

【讨论】:

  • 我的意思是连续上下移动它意味着它永远不会停止这样做。不过感谢您的回答。
  • 要停止它或改变方向,您必须使用move_up = True 和一些if/else 等变量来检查何时改变方向。
  • 如何让这个连续?
  • 查看答案中的新示例
  • 另一个例子 - 在画布上移动
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多