问题
The following code behaves differently in different environments.
On my Windows machine (Windows 10, Python 3.6), each keypress creates a response and then nothing happens until I press a key again.
On "Python Trinkets" (https://trinket.io/python) I don't need to repeat the keypress, as holding the key down creates repeat events.
I know that the Trinket version is a JS implementation, but does that explain the difference entirely? Would the program behave the same on Linux or OS?
More importantly, is there a way to make it work on Windows so that holding a key down creates repeat events?
# import the turtle module so we can use all the neat code it contains
import turtle
# Create a variable `tina` that is a Turtle() object. Set shape to 'turtle'
tina = turtle.Turtle()
tina.shape('turtle')
# Create a variable `screen`, a Screen() object, that will handle keyss
screen = turtle.Screen()
# Define functions for each arrow key
def go_left():
tina.left(7)
def go_right():
tina.right(7)
def go_forward():
tina.forward(10)
def go_backward():
tina.backward(10)
# Tell the program which functions go with which keys
screen.onkey(go_left, 'Left')
screen.onkey(go_right, 'Right')
screen.onkey(go_forward, 'Up')
screen.onkey(go_backward, 'Down')
# Tell the screen to listen for key presses
screen.listen()
turtle.done()
回答1:
Ok, I've found the solution.
The Trinket (JS) implementation is inaccurate.
Using this code: wn.onkey(go_up, "Up")
binds the function to the key-press event in "standard" Python, which means the function is only called once.
To have it repeat while the key is held down, the following is needed:
def move(event):
my_turtle.forward(5)
turtle.getcanvas().bind('<Up>', move)
回答2:
is there a way to make it work on Windows so that holding a key down creates repeat events?
Key repeat is an operating system function and different systems handle it differently. For example, the keys on my Apple OS X system repeat by default but I can go into System Preferences / Keyboard and change the rate and even turn it off (which I did to test the code below.)
If you don't have key repeat and want to simulate it, here's a simple example of using a turtle timer event to start a key repeating on key down and turn it off on key up:
# import the turtle module so we can use all the neat code it contains
from turtle import Turtle, Screen
KEY_REPEAT_RATE = 20 # in milliseconds
# Create a variable `tina` that is a Turtle() object. Set shape to 'turtle'
tina = Turtle('turtle')
# Create a variable `screen`, a Screen() object, that will handle keys
screen = Screen()
# Define functions for each arrow key
def go_left():
tina.left(7)
if repeating:
screen.ontimer(go_left, KEY_REPEAT_RATE)
def go_right():
tina.right(7)
if repeating:
screen.ontimer(go_right, KEY_REPEAT_RATE)
def go_forward():
tina.forward(10)
if repeating:
screen.ontimer(go_forward, KEY_REPEAT_RATE)
def go_backward():
tina.backward(10)
if repeating:
screen.ontimer(go_backward, KEY_REPEAT_RATE)
def start_repeat(func):
global repeating
repeating = True
func()
def stop_repeat():
global repeating
repeating = False
repeating = False
# Tell the program which functions go with which keys
screen.onkeypress(lambda: start_repeat(go_left), 'Left')
screen.onkeyrelease(stop_repeat, 'Left')
screen.onkeypress(lambda: start_repeat(go_right), 'Right')
screen.onkeyrelease(stop_repeat, 'Right')
screen.onkeypress(lambda: start_repeat(go_forward), 'Up')
screen.onkeyrelease(stop_repeat, 'Up')
screen.onkeypress(lambda: start_repeat(go_backward), 'Down')
screen.onkeyrelease(stop_repeat, 'Down')
# Tell the screen to listen for key presses
screen.listen()
screen.mainloop()
However, your challenge is to figure out when you need this simulated repeat and when the system already has repeat capability -- having both active will be messy.
来源:https://stackoverflow.com/questions/44863600/turtle-graphics-keypress-event-not-repeating