Tkinter & Turtle Etch-a-Sketch

Я работал над созданием программы, похожей на etch-a-sketch, где вы можете использовать клавиши со стрелками для рисования. Я заметил, что не могу удерживать две клавиши, чтобы перемещаться по экрану, как клавиши со стрелками вверх и влево. Возможно ли это и как я могу это сделать?

Вот мой код:

import tkinter as tk
import turtle

def k1(event):
    t.forward(1)

def k2(event):
    t.left(1)

def k3(event):
    t.right(1)

def k4(event):
    t.back(1)

window = tk.Tk()

window.geometry("750x500")
window.resizable(False, False)

canvas = tk.Canvas(master=window, width=500, height=500, bg="white")
canvas.pack()

t = turtle.RawTurtle(canvas)

window.bind("<Up>", k1)
window.bind("<Left>", k2)
window.bind("<Right>", k3)
window.bind("<Down>", k4)

window.mainloop()

person Deon Leggett    schedule 28.01.2020    source источник
comment
Я не понимаю вашей проблемы. Когда я нажимаю стрелку влево или вправо, стрелка на экране вращается, затем я нажимаю вперед, и она движется в этом направлении. Он работает во всех направлениях, так что вы имеете в виду по всему экрану? Он идет по экрану в любом направлении для меня. Если вы не хотите, чтобы он двигался вперед, одновременно поворачиваясь, вам следует уточнить это в своем вопросе.   -  person Mike - SMT    schedule 28.01.2020
comment
Я имею в виду, что вы можете одновременно удерживать клавиши «вверх» и «влево», чтобы он двигался в направлении \, а не продолжал переключаться между клавишами «вверх» и «влево».   -  person Deon Leggett    schedule 28.01.2020
comment
Если это так, проверьте этот пост. stackoverflow.com/a/44086242/7475225 . Одно только нормальное связывание не может сделать то, что вы хотите. Но с некоторыми дополнительными функциями вы можете получить это.   -  person Mike - SMT    schedule 28.01.2020


Ответы (1)


Комбинируя метод, используемый Josselin в этом сообщении Нажмите 2 клавиши одновременно, чтобы двигаться по диагонали tkinter? с вашей черепашкой мы можем захватывать нажатие нескольких клавиш и что с этим делать.

Этот код позволяет вам нажимать несколько клавиш одновременно, чтобы получить хотя бы вращательное движение.

import tkinter as tk
import turtle


window = tk.Tk()
window.geometry("750x500")
window.resizable(False, False)
pressedStatus = {"Up": False, "Down": False, "Left": False, "Right": False}
canvas = tk.Canvas(master=window, width=500, height=500, bg="white")
canvas.pack()

t = turtle.RawTurtle(canvas)

def pressed(event):
    pressedStatus[event.keysym] = True

def released(event):
    pressedStatus[event.keysym] = False

def set_bindings():
    for char in ["Up", "Down", "Left", "Right"]:
        window.bind("<KeyPress-%s>" % char, pressed)
        window.bind("<KeyRelease-%s>" % char, released)

def animate():
    if pressedStatus["Up"]: t.forward(1)
    if pressedStatus["Down"]: t.back(1)
    if pressedStatus["Left"]: t.left(1)
    if pressedStatus["Right"]: t.right(1)
    canvas.update()
    window.after(10, animate)

set_bindings()
animate()
window.mainloop()

Приложив немного больше усилий и еще один словарь для отслеживания поворота, мы можем получить диагональные линии любой степени, которую вы хотите. Я предполагаю, что 45 градусов - это цель, поэтому попробуйте следующее.

import tkinter as tk
import turtle


window = tk.Tk()
window.geometry("750x500")
window.resizable(False, False)
pressed_status = {"Up": False, "Down": False, "Left": False, "Right": False}
rotation_lock = {"Left": False, "Right": False}  # use to lock the rotation event so we cont constantly rotate.
canvas = tk.Canvas(master=window, width=500, height=500, bg="white")
canvas.pack()

t = turtle.RawTurtle(canvas)

def pressed(event):
    pressed_status[event.keysym] = True

def released(event):
    pressed_status[event.keysym] = False
    if event.keysym == 'Left' or event.keysym == 'Right':
        rotation_lock[event.keysym] = False

def set_bindings():
    for char in ["Up", "Down", "Left", "Right"]:
        window.bind("<KeyPress-%s>" % char, pressed)
        window.bind("<KeyRelease-%s>" % char, released)

def animate():
    # By first checking if 2 keys are pressed we can make sure we get the rotation we are looking for.
    # Then if not 2 keys then process single keys.
    # We also want to lock the rotation after our first rotation as to not constantly turn at a 45 degree angle.
    if pressed_status["Up"] and pressed_status["Left"]:
        t.forward(1)
        if not rotation_lock['Left']:
            rotation_lock['Left'] = True
            t.left(45)
    elif pressed_status["Up"] and pressed_status["Right"]:
        t.forward(1)
        t.right(1)
        if not rotation_lock['Right']:
            rotation_lock['Right'] = True
            t.right(45)
    elif pressed_status["Down"] and pressed_status["Left"]:
        t.back(1)
        if not rotation_lock['Left']:
            rotation_lock['Left'] = True
            t.left(45)
    elif pressed_status["Down"] and pressed_status["Right"]:
        t.back(1)
        if not rotation_lock['Right']:
            rotation_lock['Right'] = True
            t.right(45)

    elif pressed_status["Up"]: t.forward(1)
    elif pressed_status["Down"]: t.back(1)
    elif pressed_status["Left"]: t.left(1)
    elif pressed_status["Right"]: t.right(1)
    canvas.update()
    window.after(40, animate)

set_bindings()
animate()
window.mainloop()

Если мы добавим к миксу 3-ю клавишу, мы сможем переключаться между диагональными и кривыми линиями.

Взгляните на этот пример:

import tkinter as tk
import turtle


window = tk.Tk()
window.geometry("750x500")
window.resizable(False, False)
pressed_status = {"Up": False, "Down": False, "Left": False, "Right": False, "Control_L": False}
rotation_lock = {"Left": False, "Right": False}  # use to lock the rotation event so we cont constantly rotate.
canvas = tk.Canvas(master=window, width=500, height=500, bg="white")
canvas.pack()

t = turtle.RawTurtle(canvas)

def pressed(event):
    pressed_status[event.keysym] = True

def released(event):
    pressed_status[event.keysym] = False
    if event.keysym == 'Left' or event.keysym == 'Right':
        rotation_lock[event.keysym] = False

def set_bindings():
    for char in ["Up", "Down", "Left", "Right", "Control_L"]:
        window.bind("<KeyPress-%s>" % char, pressed)
        window.bind("<KeyRelease-%s>" % char, released)

def animate():
    # By first checking if 2 keys are pressed we can make sure we get the rotation we are looking for.
    # Then if not 2 keys then process single keys.
    # We also want to lock the rotation after our first rotation as to not constantly turn at a 45 degree angle.
    if pressed_status["Up"] and pressed_status["Left"]:
        t.forward(1)
        if pressed_status["Control_L"]:
            t.left(1)
        else:
            if not rotation_lock['Left']:
                rotation_lock['Left'] = True
                t.left(45)
    elif pressed_status["Up"] and pressed_status["Right"]:
        t.forward(1)
        if pressed_status["Control_L"]:
            t.right(1)
        else:
            if not rotation_lock['Right']:
                rotation_lock['Right'] = True
                t.right(45)
    elif pressed_status["Down"] and pressed_status["Left"]:
        t.back(1)
        if pressed_status["Control_L"]:
            t.left(1)
        else:
            if not rotation_lock['Left']:
                rotation_lock['Left'] = True
                t.left(45)
    elif pressed_status["Down"] and pressed_status["Right"]:
        t.back(1)
        if pressed_status["Control_L"]:
            t.right(1)
        else:
            if not rotation_lock['Right']:
                rotation_lock['Right'] = True
                t.right(45)

    elif pressed_status["Up"]: t.forward(1)
    elif pressed_status["Down"]: t.back(1)
    elif pressed_status["Left"]: t.left(1)
    elif pressed_status["Right"]: t.right(1)
    canvas.update()
    window.after(40, animate)

set_bindings()
animate()
window.mainloop()

введите здесь описание изображения

person Mike - SMT    schedule 28.01.2020