OnscreenText and setText [Hint]

hi there,

have a look at this example. it’s just there to demonstrate an effect. the goal: to print something on the screen and change the text on-the-fly (by some task in this case).

import direct.directbase.DirectStart

from direct.task import Task 
from direct.gui.OnscreenText import OnscreenText

mytext = OnscreenText(text='clock:', pos=(-0.5, 0.02), scale=0.07, fg=(1, 1, 1, 1))

def changeText(task):
    mytext.setText('clock:' + str(globalClock.getDt()))
    return Task.cont
    
taskMgr.add(changeText, 'changeText')    
    
run()

funny thing - this does not work - you’ll get:

looking into the approriate module OnscreenText.py, you’ll realize that there is an “optimization” happening. depending if the OnscreenText constructor is provided with an initial text string or not, the corresponding self.textNode is either

changing the constructor to


mytext = OnscreenText(pos=(-0.5, 0.02), scale=0.07, fg=(1, 1, 1, 1))

and the problem is solved, the program runs as wanted. or you might also want to pass myChange=True to the constructor.

this post is just here to inform others about this behaviour. the exception was not clear to me and i had to dig into OnscreenText.py to understand this. we might want to add a hint regarding myChange in the manual?

cheers,
kaweh

just realized: even if you pass mayChange=True to the constructor and give a text, the text is going to be static and you’ll end up with an exception. personally i think that’s not quite the behaviour i would expect.

shall we fix that? i propose that mayChange defaults to False and is not influenced by giving a text or not at construction time. patch is really simple.

panda3d dev team, what do you think?

Hmm, are you sure? I find through examining the code, and through experimentation to verify, that there are four cases:

mayChange unspecified, text unspecified: text is modifiable
mayChange = 1, text unspecified: text is modifiable
mayChange unspecified, text given: text is not modifiable
mayChange = 1, text given: text is modifiable

Thus, whenever you pass mayChange = 1, whether or not you also supply a text string to the constructor, then you can modify the text later. Also, if you do not pass mayChange = 1 (or you pass mayChange = 0, which is the default), then the text is modifiable only if you do not supply a text string to the constructor (because obviously you intend to be modifying the text, since it wasn’t available at construction time).

So it sounds like the code is already behaving the way you say it should. I guess if we wanted to remove the funny implicit mayChange = 1 in the case that no text is supplied to the constructor, we could make it trigger an immediate exception if you invoke the constructor without specifying a text string or specifying mayChange = 1, but I’m not sure if this really improves the interface or not.

David

Over one year after this post I had the same problem. First I found on http://panda3d.org/manual/index.php/OnscreenText the sentence “This may be omitted and specified later via setText() if you don’t have it available, but it is better to specify it up front.” and was surprised that setText(text) wasn’t found when I run the script. Next in the API reference http://panda3d.org/apiref.php?page=OnscreenText#setText setText(text) is undocumented. In my opinion finding the answer first in this old thread is a bad solution.

@kaweh: if you’re still an active user please edit your post and write mayChange correct (with an “a”).

neo

I believe setText is used internally, so if you need to change the text, use :

yourOST['text']='xxxxx'

I believe setText is used to update the text. So after you’ve done obj[‘text’]=blah, you should use setText() to update it internally.

Wait, you two guys are confusing OnscreenText with DirectLabel et al. OnscreenText provides the setText() call, which the user is intended to use to change the text. DIrectGui elements don’t provide a public setText() call and expect the user to change the text with the indexing operator.

Although, huh, I just noticed that at some point, someone has added the indexing operator to OnscreenText, so you can also set the text with obj[‘text’] = blah. How weird and confusing that is. Well, still, a direct call to setText() works just fine also, and is the original intended way to change the text (which is different from the original intended way to change the text for a DirectGui object, which requires that weird obj[‘text’] syntax).

The first answer in the thread is still correct: mayChange needs to be explicitly specified if you expect to call setText() later. That this is not properly documented is certainly a documentation bug.

Arguably, though, mayChange isn’t really needed these days. It was added many years ago, when a TextNode was really expensive. Nowadays it has about the same cost as the equivalent GeomNode, so it doesn’t really buy you that much to replace the TextNode with a GeomNode. Therefore, in the interest of reduced future confusion, I’ve just checked in a change to set mayChange = True by default.

David