Jump to content

Python onkey/onkeypress function activating without me pressing any keys

Go to solution Solved by DANK_AS_gay,
22 minutes ago, Linus No Beard said:

It looks like your code is creating a new turtle and assigning it a letter every time the function havefun is called. It appears that the havefun function is called 5 times when the code first runs, which is why you see the letters being drawn without any input from you.

If you want the letters to only be drawn when a key is pressed, you can move the call to havefun inside of a function that is called when a key is pressed. You can use the onkeypress method of the Screen object to register a function to be called when a key is pressed.

That's not specifically what I was talking about, but I want those 5 turtles objects created, as they are the first 5 turtles you use to start the "game" so to speak. The problem I was having is that the "onkeypress" function was running the callback without the key being pressed.

 

Anyways, I figured out a solution, it looks like this:

wn.onkey(lambda n = "A": keyfilter(n),"A")

The onkey function does not support passthrough. So what was happening is that the function was being called without the key needing to be pressed. I am not clear on how this "lambda" thing works, but it does, so...

import turtle as trtl
import random as rand
import time


#-----setup-----
apple_image = "apple.gif" # Store the file name of your shape
letterlist = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]

wn = trtl.Screen()
wn.setup(width=1.0, height=1.0)
wn.bgpic("background.gif")
wn.addshape(apple_image)
wn.tracer(False) # Make the screen aware of the new file

apple = trtl.Turtle()
apple.penup()
apple.hideturtle()

letterchoicevar = ''
apple_turtles = []
atactiveletters = []
letter_turtles = []
clear = False
numberturtles = 0
index = 0




#-----functions-----
# given a turtle, set that turtle to be shaped by the image file

def havefun():
  global numberturtles
  letterchoice()
  atactiveletters.append(letterchoicevar)
  at = trtl.Turtle()
  at.penup()
  at.shape(apple_image)
  at.goto((rand.randint(-200,200), rand.randint(-10,100)))
  at.stamp()
  at.hideturtle()
  lettery = (at.ycor() - 40)
  letterx = (at.xcor() - 18)
  at.goto(letterx,lettery)
  at.color('white')
  at.write(letterchoicevar, font=("Arial", 55, "bold"))
  apple_turtles.append(at)
  print(len(apple_turtles))
  numberturtles += 1
  wn.update()



def letterchoice():
  global letterchoicevar
  letterchoicevar = letterlist[(rand.randint(0,(len(letterlist)-1)))]


while numberturtles < 5:
  havefun()


def keyfilter(passthrough):
  index = 0
  if passthrough in atactiveletters:
    while (atactiveletters[index] != passthrough) and index <4:
      index += 1
    apple_fall(index)
  else:
    return

def apple_fall(indexpassthrough):
  if len(apple_turtles) < 5:
    havefun()
  global numberturtles
  active_apple = apple_turtles.pop(indexpassthrough)
  atactiveletters.pop(indexpassthrough)
  letterchoice()
  atactiveletters.append(letterchoicevar) 
  appley = active_apple.ycor()
  apple_offset = abs(-160 - appley)
  active_apple.setheading(270)
  active_apple.forward(apple_offset)
  active_apple.hideturtle()
  active_apple.clear()
  numberturtles = (numberturtles - 1)
  wn.update()

  




    
#TODO Create a function that takes a turtle as its parameter and gives that turtle (apple)
# a new location on the tree, only if the list of letters is not empty. Associate the 
# turtle with a new letter selected at random from the list of letters
#def apple_pos():
  
#TODO Create a function that takes a turtle (apple) and its corresponding letter from the letter
# list and draws that letter on that turtle (apple)

#TODO Create a function that takes a turtle (apple) and its corresponding ltter from the letter
# list and set that turtle to be shaped by the image file, call the letter drawing function,
# and update the Screen

#TODO Iterate over the numbers from 0 to the number of apples, creating that many turtles
# calling your function that resets the apples by giving them a new random location
# add the new apples to a list of apples to be used in the rest of the program.
# The loop below executes the correct number of times by using the range() function
# to create a list of numbers to iterate over.
#'''for i in range(0, number_of_apples):

#TODO Create a function that takes a letter as its parameter, uses that letter to retrieve the
# corresponding turtle (apple) and causes both to drop from the tree simultaneously. Once the 
# apple and letter have dropped, call the apple reseting function.

#TODO define a function per letter that you will use in your program. Each function should check
# to see if the given letter is in the list of letters; if it is, it should drop the corresponding
# apple.

#TODO use the onkeypress method of wn to correlate the functions you defined above with each
# of the letters that the user might type.
# onkeypress requires that you name one function that must take
# no arguments to be called when the specified key is pressed.


  
#-----function calls-----

while True:
    wn.onkey(keyfilter("A"),"A")
    wn.onkey(keyfilter("B"),"B")
    wn.onkey(keyfilter("C"),"C")
    wn.onkey(keyfilter("D"),"D")
    wn.onkey(keyfilter("E"),"E")
    wn.onkey(keyfilter("F"),"F")
    wn.onkey(keyfilter("G"),"G")
    wn.onkey(keyfilter("H"),"H")
    wn.onkey(keyfilter("I"),"I")
    wn.onkey(keyfilter("J"),"J")
    wn.onkey(keyfilter("K"),"K")
    wn.onkey(keyfilter("L"),"L")
    wn.onkey(keyfilter("M"),"M")
    wn.onkey(keyfilter("N"),"N")
    wn.onkey(keyfilter("O"),"O")
    wn.onkey(keyfilter("P"),"P")
    wn.onkey(keyfilter("Q"),"Q")
    wn.onkey(keyfilter("R"),"R")
    wn.onkey(keyfilter("S"),"S")
    wn.onkey(keyfilter("T"),"T")
    wn.onkey(keyfilter("U"),"U")
    wn.onkey(keyfilter("V"),"V")
    wn.onkey(keyfilter("W"),"W")
    wn.onkey(keyfilter("X"),"X")
    wn.onkey(keyfilter("Y"),"Y")
    wn.onkey(keyfilter("Z"),"Z")
    
    wn.listen()
    wn.update()

I know the wn.update() isn't ideal, it's there to slow down the code so it doesn't hang on my computer.
Basically, the only reference to the "apple_fall" function is the onkey functions at the bottom of my code, and yet the function is being called without me pressing any keys. I have looked the functions up for help, and asked my teacher, but I found no sources due to other modules advertising their keyboard plugin.

Link to post
Share on other sites

It looks like your code is creating a new turtle and assigning it a letter every time the function havefun is called. It appears that the havefun function is called 5 times when the code first runs, which is why you see the letters being drawn without any input from you.

If you want the letters to only be drawn when a key is pressed, you can move the call to havefun inside of a function that is called when a key is pressed. You can use the onkeypress method of the Screen object to register a function to be called when a key is pressed.

Link to post
Share on other sites

22 minutes ago, Linus No Beard said:

It looks like your code is creating a new turtle and assigning it a letter every time the function havefun is called. It appears that the havefun function is called 5 times when the code first runs, which is why you see the letters being drawn without any input from you.

If you want the letters to only be drawn when a key is pressed, you can move the call to havefun inside of a function that is called when a key is pressed. You can use the onkeypress method of the Screen object to register a function to be called when a key is pressed.

That's not specifically what I was talking about, but I want those 5 turtles objects created, as they are the first 5 turtles you use to start the "game" so to speak. The problem I was having is that the "onkeypress" function was running the callback without the key being pressed.

 

Anyways, I figured out a solution, it looks like this:

wn.onkey(lambda n = "A": keyfilter(n),"A")

The onkey function does not support passthrough. So what was happening is that the function was being called without the key needing to be pressed. I am not clear on how this "lambda" thing works, but it does, so...

Link to post
Share on other sites

Lambdas are basically shorthand for functions you can call to do things in response to an event, such as onKey here in Python.  The syntax is awful, though.  JavaScript might be a bit more clear:
 

var obj; // Imagine this is assigned to a DOM object via document.getObjectById()

obj.addEventListener('click', (event) => {
    // Do some stuff
});

That second line is the same as writing

obj.addEventListener('click', function(event) {
    // Do some stuff
});

 

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×