I am trying to add 1 every time I release a key:
from turtle import *
import turtle
turtle1 = Turtle()
screen = turtle1.getscreen()
goPressed = False
imported Turtle...
currentWatts=0
def onaclicked():
global currentWatts
currentWatts+=1
print (currentWatts)
defined my function to be run when the key: 1, is released
turtle.onkeyrelease(onaclicked, "1")
for some reason onkeyrelease isn't there even though I imported Turtle and checked in Python documentation. It SHOULD work, shouldn't it? Did I improperly import? Can you please help me?
The reason I want it to be onkeyrelease instead of onkey, is because it is for a game. With onkey, when you hold your finger on the key, it adds 1 to currentWatts every around 0.25 seconds. You could cheat by placing something on the key so I want it only to add 1 when you release the key.
You've several problems with your code: you import turtle two different ways which confuses things; onkeyrelease() is really a method of the screen/window, not a turtle; you didn't call listen() which allows keystrokes to be processed. The following should work in Python 3:
from turtle import Turtle, Screen, mainloop
def onaclicked():
global currentWatts
currentWatts += 1
print(currentWatts)
currentWatts = 0
screen = Screen()
screen.onkeyrelease(onaclicked, "1")
screen.listen()
mainloop()
Make sure to click on the window once before you start typing to make it active.
If you're using Python 2, which I suspect from the error message you got, then replace the Python 3 alias onkeyrelease with onkey:
The method Screen.onkeypress() has been added as a complement to
Screen.onkey() which in fact binds actions to the keyrelease event.
Accordingly the latter has got an alias: Screen.onkeyrelease().
This change should work the same in both versions. Using onkeyrelease instead of onkey wasn't going fix your holding a finger on the key issue.
when you hold your finger on the key, it adds 1 to
currentWatts every around 0.25 seconds. You could cheat by placing
something on the key so I want it only to add 1 when you release
It appears that automatic key repeats are handled by the operating system and may need to be disabled external to Python, depending on the OS. Some example links:
Apple OSX: Set how quickly a key
repeats
Ubuntu: Turn off repeated key
presses
X-Windows from Python: key repeat in
tkinter
Related
(I drastically simplified my code now so you should also be able to run it.)
Like I said in the previous version of this question, I am trying to get tkinter to process arrow key strokes. The following code produces a grid of $-signs with one I in the middle (the agent). All it is supposed to do for now is, on pressing the up key, move the agent up and collect a $-sign.
'''
import tkinter as tk
class PlayGame:
def __init__(self):
self.history=[] #Will contain the move history. Each element is a quadruple consisting of the state,action,reinforcement,new state.
self.root=tk.Tk()
for i in range(27):
for j in range(27):
tk.Label(self.root,text='$',height=1,width=3).grid(row=i,column=j)
self.I=[14,14]
tk.Label(self.root,text='I',height=1,width=3).grid(row=14,column=14)
self.root.bind('<KeyPress>',self.onKeyPress)
self.root.mainloop()
def onKeyPress(self,event):
if event.keysym in ['Up','Right','Down','Left']:
if event.keysym=='Up':
tk.Label(self.root,text='',height=1,width=3).grid(row=self.I[0],column=self.I[1])
tk.Label(self.root,text='I',height=1,width=3).grid(row=self.I[0]+1,column=self.I[1])
self.I[0]+=1
'''
It still doesn't work and again, something very weird happened: First, I accidentally had 'row=self.I[0],column=self.I[1]+1' instead of 'row=self.I[0]+1,column=self.I[1]'. The agent would then move to the right when I pressed the up key. After I corrected the mistake, it didn't move at all anymore. But that line can't really be the reason it is not working, can it? Does anyone have an idea why it worked initially, but suddenly not anymore?
This is the programme I wrote but I'm not sure what's wrong:-
import turtle
import random
bob = turtle.Turtle()
screen = turtle.Screen()
def coord(x,y):
print(x,y)
turtle.onscreenclick(None)
turtle.onscreenclick(coord)
turtle.listen()
print('hello')
turtle.done()
The programme works fine except that the print('hello') part happens first, followed by the on screen event. How do I make the onscreen event occur first before the rest of my programme?
You can simply make the rest of your code part of the coord function:
def coord():
print(x,y)
turtle.onscreenclick(None)
print("Hello")
# The rest of your program goes here.
However, a few things to note:
This isn't an amazing elegant solution, especially if you intend to set up other events further into your code. It can become quite hard to keep track of.
It's imperative that you remove the event binding (in this case the binding of coord to onscreenclick) as soon as it's been used, otherwise you could end up with multiple instances of the same code running at once if someone double-clicked the screen, for example. In your case you've already done this (with turtle.onscreenclick(None)), but it is something to keep in mind.
If you choose to go this route, don't forget to rename the coord function something more representative of what that section of your code will do.
I'm attempting to log coordinates 3 separate times when a user clicks on the turtle screen, then continue running other commands once that is completed. Clicking 3 times does nothing, and the shell keeps printing that it's waiting, while one additional click causes the whole thing to not work and I get a "not Responding" message from the turtle graphics window.
import turtle as t
import time
canvas=t.getcanvas()
xlist=[]
ylist=[]
listcomplete=False
def getPos(x,y):
xlist.append(canvas.winfo_pointerx()) ##Logs the x and y coords when mouse is clicked
ylist.append(canvas.winfo_pointery())
print('appended the lists.')
if len(xlist)==3:
listcomplete=True
t.onscreenclick(getPos)
def main():
while listcomplete==False:
time.sleep(1)
print('waiting...') ##Prints periodically just to let me know it's still running
main()
print('list complete.') ##Prints to alert the list has been finished
print(xlist)
(Insert rest of code to follow)
listcomplete=True within getPos() will not change the global variable, instead it will create a new varable of the same name within the local scope.
To change the global variable, you have to tell python to use it from the global scope:
def getPos(x,y):
global listcomplete # tell python to use the variable from the global scope
xlist.append(canvas.winfo_pointerx()) ##Logs the x and y coords when mouse is clicked
ylist.append(canvas.winfo_pointery())
print('appended the lists.')
if len(xlist)==3:
listcomplete=True
That's due to the default behavior of the assignment operator (=).
Other operators, such as the comparision operator (==) will lookup the variable from the enclosing scope(s) if it's not found within the local scope, thus you may use while listcomplete==False: within main() w/o telling pyton to use the variable from the global scope.
But ideally, you do not even have to use that global variable. Instead run the turtle main loop and exit the turtle window when your condition is met:
import turtle as t
canvas=t.getcanvas()
xlist=[]
ylist=[]
def getPos(x,y):
xlist.append(canvas.winfo_pointerx()) ##Logs the x and y coords when mouse is clicked
ylist.append(canvas.winfo_pointery())
print('appended the lists.')
if len(xlist)==3:
t.bye() # exit turtle window
t.onscreenclick(getPos)
t.Screen().mainloop() # will wait until turtle window is closed
print('list complete.') ##Prints to alert the list has been finished
print(xlist)
Is it possible to continue running the turtle window after the lists
have been created?
Things get difficult in turtle when you fight it's event-based model as you're trying to do. Work with the model, and things get easier. The code below presents a blank window, after you click on it in three places, it will connect your points to make a triangle:
from turtle import Screen, Turtle, mainloop
def getPosition(x, y):
screen.onscreenclick(None) # disable the handler inside the handler
positions.append((x, y))
if len(positions) == 3:
screen.ontimer(listComplete) # sometime after this function completes
else:
screen.onscreenclick(getPosition) # restore the handler
def listComplete():
for position in positions:
turtle.goto(position)
turtle.pendown()
turtle.goto(positions[0]) # close our triangle
# (Insert rest of code to follow)
positions = []
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
screen = Screen()
screen.onscreenclick(getPosition)
mainloop() # invoke as function to make Python 2 friendly as well
The key is that "rest of code to follow" will be in functions, not top level code.
def handle_click(mouse_x,mouse_y): # <== I think thats what ya need right dere, I dont think it knows you're clicking
newpin = [[mouse_x,mouse_y], [0,0], 0,0,20, 1000000]
I tried putting a print statement after the click I couldn't get it to even print a test click. That may be me not trying hard enough tho ;) I just remember using something like above to handle a mouse click. (in my situation it created a pin for a pinball game) if you look up the turtle api for circle you can see the [0,0],0,0,20, 100000] means.
But ultimately that last number the 10000 whatever is "mass" so the more of it the less it moves. again my situation. turtle.onscreenclick(handle_click). Thats at least an idea :) also yes u can do a wait after an if. Throw in print statements.
Despite hunting around I can't seem to find an answer to this seemingly simple question:
I'm new to pygame (but not to python), and am trying to get some code to work from continuous button presses - but get_pressed just does not seem to work for me. I made this just to check that I wasn't going insane (I've left out the importing to make it neat for you guys):
def buttonpress():
while True:
keys = pygame.key.get_pressed()
print keys[K_SPACE]
time.sleep(0.5)
buttonpress()
To the best of my knowledge, this should return a '1' when you press the space bar, but no matter what key you change it too - it simply returns an endless string of zeros.
What am I missing?
Thanks
There is no code that processes the input to get all the keys pressed. In order for this to work you need to call event.poll().
So your code will look like this.
import pygame
from pygame.locals import *
import time
pygame.init()
screen = pygame.display.set_mode((640,380))
def buttonpress():
while True:
keys = pygame.key.get_pressed()
print (keys[K_SPACE])
time.sleep(0.5)
pygame.event.poll()
buttonpress()
One more thing, do not use time.sleep(). This pauses the thread, and can cause the OS to think that your application does not respond (since it's not removing events from the event queue).
I'll admit, i am a newbie with python, but here is my issue.
the version is 2.6.5 (i know i'ts an old version but there's reasons to this) and livewires is used
Bascially this game has a bunch of colored balloons in which you need to click them to make them disappear. Adjacent balloons of the same color disappear along with the clicked balloon. Once the balloons are cleared it moves on to the next level.
I need to create a timer on the top right of my screen. This timer needs to countdown in seconds (from 30 might be a good start.) However no matter what i try, either the timer does not display or the numbers are overlap eachother. I would like to know how to do this, as it has been driving me up the wall as of late.
...Of course it also needs to end the game if it reaches zero and add more time if the level is complete...
But for now i just want to focus on displaying the timer and having it count down to zero on screen.
class Timer(games.Sprite):
""" countdown timer """
def __init__(self):
timer_message = games.Text(
value = 30,
size = 50,
color = red,
x = 600,
y = 30
)
def start(self):
while self.timer_message.value != 0:
time.sleep(1)
self.timer_message.value -= 1
game.screen.add(timer_message)
Alright. I fixed the "compressing balloons table" (accidentally deleted the self_update lol) problem, but now it is saying that "global name timer_message is not defined"... despite the fact that it says timer_message = games.Text
I would paste the whole code, but i can't get the indentation right (this is my first time using this website.)
So, I understand it's been some time and if you don't need an answer anymore that's alright.
For now it's hard to answer your question in general because I don't understand the structure of the rest of your code or how you're displaying graphics. However, I can tell you while you're getting the
global name timer_message is not defined
error. It's because when you define timer_message within the __init__ function you are defining it within the local scope of the function but not for the class. In order to make it accessible to the class you need to assign to self.timer_message.
This is a consequence of how python imitates object oriented programming, but making this change should address your immediate error.