DirectLabel or OnscreenText -- maintaining vertical center

Greetings all!

I’m constructing a little message box (i.e. a feedback box to notify the user of events in the game) using DirectLabel. The format for the box will essentially be like this:


+--------------+
|  Some text   |
|     that     |
|  is centered |
+--------------+

The text word-wraps at a fixed width and maintains the desired horizontal alignment (by specifying TextNode.ACenter), but I’d also like it to vertically-align on the center of the DirectLabel object.

Is there an option to trigger this behavior? If not, has anyone settled upon a “standard technique” to do this? I was planning to construct my text in a TextNode and then use the getHeight() function to manually offset the “text” component of the DirectLabel, but there may be a better way…

Thanks!
Mark

There’s nothing built-in to achieve the vertical centering effect you describe, but using TextNode.getHeight() sounds like a perfectly good way to do it by hand.

David

Sorry to dig out such an old thread but I had exactly the same problem and found no solution.
So, taking the hints from above, I wrote the following utility function that adds a TextNode to a DirectFrame (or a DirectButton, DirectLabel, …) and centers the text vertically. It also accounts for non-centered specified frame sizes (e.g. frameSize=(-0.5, 1.0, 0.0, 1.0)).

def add_centered_text(direct_gui: DirectFrame,
                      text: str,
                      scale: float,
                      font: Optional[TextFont] = None):
    text_node = TextNode('text_node')
    text_node.setText(text)
    text_node.setAlign(TextNode.ACenter)
    if font:
        text_node.setFont(font)    
    tnp: NodePath = direct_gui.attachNewNode(text_node)
    tnp.setScale(scale)
    tnpb = tnp.getTightBounds()
    c = [(direct_gui['frameSize'][0] + direct_gui['frameSize'][1]) / 2,
         (direct_gui['frameSize'][2] + direct_gui['frameSize'][3]) / 2]
    c2 = [(tnpb[1][0] + tnpb[0][0]) / 2, (tnpb[1][2] + tnpb[0][2]) / 2]
    tnp.setPos(c[0], 0, c[1] - c2[1])

I don’t know if that is the best way to do it but it seems to do the trick for me.

Note that the text will be centered vertically based on its entire height. E.g… “Axq” will be centered at the cross point of the x roughly since the A sticks out to the top roughly the same distance that q does to the bottom. On the other hand, “Abc” will be centered roughly w.r.t. the horizontal bar of the letter A.
I checked with Qt and this is not exactly the same behavior they implemented for QButton and QLabel, but it’s still a significant improvement over the default behavior of DirectLabel for me.

Best
Niklas

1 Like