Pygame text not updating - python

The following code is being looped - is in a loop - but when 'inputStr' changes, the display does not. Printing inputStr yields the expected results, though.
defFnt = pygame.font.Font("CP437.ttf", 72)
txtToRndr = defFnt.render(inputStr,False, (0,0,0))
disp.blit(txtToRndr, (100,300))
Download link; http://www.mediafire.com/download/a4hp9wgojxgiao9/functGroup.rar

If you print inputStr right before its rendered it prints for a bit then stops, meaning it isnt getting rendered after a certain point, Which i think is because this condition:
if (16-len(Gnots))>0:
it must be coming out false therefore the code to render the new text isnt being executed:
if you print Gnots after the condition, it prints it until its length is 16 items than stops
change the number 16 in the condition to say 1000 as a test than try typing and the text changes

Your code needs refactoring. As the other answer says, the main problem is that if-block (try changing it to if True:.
I would recommend capping the framerate but drawing every frame unconditionally, as this is simpler and more robust. You're also not clearing the screen each frame, and PyGame has nice key tokens (e.g. pygame.K_ESCAPE) which you should use instead of numbers. You're also loading the font each time you draw; you only need to do so once, at the top of your program.
Here's my PyGame basecode, which shows some of these best practices. In the draw() function, you'd add your fill call to clear the screen, and then all of your rendering code.

I can suggest the following after encountering similar issue.
Try updating the screen with your text by adding following line after your code:
pygame.display.update()
The issue of text not updating on screen was coming in my case as I was trying to take input from terminal and then updating in on pygame screen.

Related

how to update stdscr size with python curses after resizing the terminal

I tried searching everywhere on the internet, but nowhere did I find an answer that worked for me, so I'm asking a new question.
In my code, I'm telling curses to get the terminal size and update some variables according to it. On my first try, I did something like this (this is the function that gets called after the window has been resized manually):
def resize():
rows, cols = stdscr.getmaxyx()
#some more code irrelevant to the question
When I found out that doesn't work, I realised that the stdscr is probably not getting resized, even though the terminal is. So I tried closing the stdscr and initialising it again:
def resize():
curses.endwin()
curses.wrapper(initialise)
#some more code that's irrelevant to the question
#showing the initialise function just in case:
def initialise(stdscrarg):
global stdscr
stdscr = stdscrarg
That, however, also didn't work. In other words, the stdscr initialised in the size that the terminal had before resizing. i.e. if I had a terminal over a quarter of my screen and then resized it to full screen, the function would correctly deal with the warping of the text, but it would redraw the content adjusted to just the original quarter of the screen, and would leave the junk characters in the rest of the screen, like this:
Before resizing
After resizing, before refreshing
After refreshing.
As you can see, the stdscr has initialised to its original size instead of taking on the size of the terminal. And I have tested it and confirmed that it really is the size of the stdscr, and not just the text printed on it (as when I gradually add strings to it, it throws an error when it reaches the end of the original size screen, instead of continuing to the end of the terminal screen and only then throwing an error.)
My question is: How can I get the new size of the terminal and make stdscr initialise with this new size?
Working on Windows 11, Python 3.10, module curses (though when installing it through pip, its name is windows-curses)

Using onscreen.click() in turtle but only works at the end of the programme

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.

How to use the same key to flip multiple times in PsychoPy?

I’m trying to use the same key to flip after multiple successive stimuli in PsychoPy but it keeps flipping successive screens as well then.
What I came up with was the following slight modification of one of the examples in the manual:
from psychopy import visual, core, event
win = visual.Window(monitor="testMonitor", units="deg")
stim1 = visual.TextStim(win, text="Stim 1", pos=(0,0))
stim2 = visual.TextStim(win, text="Stim 2", pos=(0,0))
stim3 = visual.TextStim(win, text="Stim 3", pos=(0,0))
while len(event.getKeys(['space'])) <= 0:
stim1.draw()
win.flip()
event.clearEvents()
print(event.getKeys()) # test if key buffer is really empty
win.flip()
# while len(event.getKeys(['return'])) <= 0:
# stim2.draw()
# win.flip()
# event.clearEvents()
# win.flip()
while len(event.getKeys(['space'])) <= 0:
stim3.draw()
win.flip()
event.clearEvents()
win.flip()
win.close()
core.quit()
However if I hit space on the first screen, it doesn’t just flip this screen. Instead it will flash stim3 for a split second and then immediately terminate. If on the other hand I use a different key for the second stimulus (replace 'space' with 'return' in the loop condition), that works fine.
My first suspicion was that event.clearEvents() somehow failed to clear the event buffer, so the space event from the first stimulus remained saved and also flipped the second stimulus. However in that case the stim3 shouldn’t be shown at all because the loop condition would immediately fail. Also, if I print out event.getKeys() at the indicated position above, it appears to be empty. Moreover, if I use a different key between the two space-triggered stimuli (remove comments from the stim2 section), suddenly all keys work just fine.
Does anybody have an idea what I’m doing wrong?
(Btw if you’re wondering: I modified the manual example by changing the loop where the program waits for input from a while True loop into while len(event.getKeys(['space'])) <= 0 which eliminates the need of using the exact same condition to break. I tested it with the original idiom just to be sure and the behaviour is the exact same as with my version.)
After some more testing found that deleting the win.flip()'s after each event.clearEvent() fixes the issue. I’m not quite sure why the additional flips (which I thought were necessary to clear the screen before drawing the new stimulus) would cause such a behaviour though. Can somebody explain?

Psychopy builder expt. - how to add live updating text on screen

I am creating an experiment using Psychopy builder.
The participant is presented with an image containing numbers, e.g. 10 and 20.
They enter what they think is the mean of the numbers, 15 in this case, and then press the spacebar to move on to the next image.
I am trying to have it so there is a display/box on screen that shows them their entry, as with larger numbers in the hundreds of thousands and millions I think they might lose track of what they have pressed.
The ability to change their entry would be excellent also, but really I am most interested in them being able to see it on screen.
In builder I can't find a way to do this, and the ratings scale is not appropriate for huge numbers.
I found these solutions in code to do something that sounds like it:
http://www.psychopy.org/wiki/home.php/Snippets/LiveUpdatingText
However when I try to add them using the code insert function , or just adding them to the compiled script the screen locks up when I try to run the experiment. I am a novice at python, and am not sure where to start fixing this. Is what I'm trying to do possible?
I'm happy to provide some example code from the compiled builder experiment.
Thanks in advance!
Those code snippets are designed for Coder, where you control everything that is happening and when. The same thing can be done in Builder, but you will have to amend the code to fit in with Builder's event loop cycle. i.e. Builder does certain things at the start of an experiment, on every trial, on every screen refresh and so on. So you can't just insert this sort of code without modification, because, for example, it attempts to wait indefinitely for a keypress. Builder meanwhile, is checking the keyboard every screen refresh (typically at 60 Hz), so if you try to wait indefinitely for a keypress in code, you'll be halting Builder from doing everything else it needs to do.
In essence, you just need to break up the code into snippets that go in the appropriate tab in a Builder Code Component (for code to be executed at experiment start, on each frame, and so on), and avoid indefinite functions like event.waitKeys() in favour of instantaneous checking via event.getKeys()
e.g. to adapt the second example from Jonas Lindeløv, in the "Begin Routine" tab, put:
chars = list('0123456789.') # the valid characters
meanText = '' # start with an empty answer on each trial
In the "Each Frame" tab, put something like:
response = event.getKeys() # get a list of keys pressed at this instant
if len(response) > 0: # if there was one,
key = response[0] # just convenient shorthand
if key in chars:
meanText = meanText + response[0]
elif key == 'space':
meanText = meanText + ' '
elif key == 'backspace' and len(meanText) > 0:
meanText = meanText[:-1]
elif key == 'return':
thisExp.addData('Answer', meanText) # save the response
continueRoutine = False # finish this trial
# update the appropriate text stimulus with the current response value:
insertNameOfYourTextStimulusComponent.text = meanText

Pygame: How would I go about setting a text object, BUT the text is meant to keep changing?

I am creating a copy of the game Pig. I have got a text based version of the game working. I am just updating it to pygame, adding graphics and sounds.
I will eventually add in mouse toggles, but for now I am trying to update a score.
I have display a 'player1 score', 'player2 score' out. I am trying to see how will it work to display text that is not constant.
i got
player1_text = font.render('player1 score', True,(0,0,0))
same for player2
I am assuming maybe that the first parameter -->'player1 score'
I can pass a variable and if I update the variable. When i call pygame.update() it should work as I think it should.
Just want some conformation or a tip on actually doing it.
Pygame Font objects are not meant to be updated and changed constantly. You will need to call render(text) each time your text changes. Render() will return a new surface, so you will need to blit that to your screen to make the change.
You're on the right track!
Use a variable.

Categories

Resources