[Ren'Py] Q: xalign misbehaving

WickedCadrach

New Member
Jul 9, 2020
6
1
Hey all, I feel like I'm missing something really basic here and I'm losing my mind trying to puzzle it out.

I want to create a frame with centered text in the top-center. When I use xalign the text either appears on the far left or 1/4 in on the left. Does anyone see what's wrong with this code? I really don't want to eyeball it with xpos.

Code:
screen pbr_test:
    frame:
        xsize 500
        ysize 400
        xalign 0.5
        yalign 0.1
        has vbox spacing 2
        
        text "BATTLE REPORT\n":
            xalign 0.5

label test:
    show screen pbr_test with dissolve
 
Apr 24, 2020
192
257
I don't know what's the cause of it, but here's how I would bodge a solution. Basically just do what align does by providing a position and anchor point for the text, rather than letting align automate the process.
Python:
screen pbr_test:
    frame:
        xsize 500
        ysize 400
        xalign 0.5
        yalign 0.1
        has vbox spacing 2
        
        text ("BATTLE REPORT\n"):
            xpos 250
            xanchor 0.5

label test:
    show screen pbr_test with dissolve
 
  • Like
Reactions: WickedCadrach

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,583
2,224
It's the has vbox that is causing your issue.

I'm randomly grasping at the documentation, so I'm not understanding WHY. But it seems something about does something to the container. There's some notes that frame: with less than one or more than one child will automatically be converted to a fixed: - but I don't think that's it.

Regardless... if you add xfill True to your vbox:, that will sort it. I just wish I could explain why it does.

Python:
screen pbr_test:
    frame:
        xsize 500
        ysize 400
        xalign 0.5
        yalign 0.1
        has vbox spacing 2 xfill True

        text "BATTLE REPORT":
            xalign 0.5

From what I can see, it's resizing the vbox to be the minimum size of it's contents (i.e. the width of the text). So whatever xalign you use, it has no room to move. I assume because the text is within the vbox rather than (or in addition to) the frame. If you add a second (larger) text line without the xfill, it will center the 1st line based on the length of the 2nd line.

Python:
screen pbr_test:
    frame:
        xsize 500
        ysize 400
        xalign 0.5
        yalign 0.1
        has vbox spacing 2

        text "BATTLE REPORT":
            xalign 0.5
        text "- - - - BATTLE REPORT (longer line) - - -":
            xalign 0.5

Personally, I'd try to ditch the has vbox line completely, but mainly only because I don't really understand what else it is doing. Since that applies to most screen: code already... I'm not really sure I'm demonstrating much except my cowardice. Good luck.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,384
15,291
Regardless... if you add xfill True to your vbox:, that will sort it. I just wish I could explain why it does.
Because without it the vbox implicitly created by has vbox have no size, and so have the size of what it contain.
Let's say that the text is 100 pixels wide, then the vbox will also be 100 pixels wide. And since the text take all the available space, it is centered... and also at the far left, as well as at the far right.

But when you add xfill True you give a size to the implicit vbox. Precisely you ask it to be as wide as its container permit it, so here the width of the frame, 500 pixels. And now that the vbox is bigger than the text, it's possible to perform some alignment.


Personally, I'd try to ditch the has vbox line completely, but mainly only because I don't really understand what else it is doing.
It just tell that the frame will act as a vbox. It create a vbox element but, as said above, it's an implicit one and people rarely give them properties ; why using something implicit when you want to treat it as something explicit ?


Therefore, something like your solution should be wrote :
Code:
screen pbr_test:
    frame:
        xsize 500
        ysize 400
        xalign 0.5
        yalign 0.1

        vbox:
            spacing 2 
            xfill True

            text "BATTLE REPORT":
                xalign 0.5
Not that it effectively change something, but by making the /vbox/ explicit, it ease the understanding of the screen structure and, possibly, make it more easy to spot the problems.


This said, the elegant solution should be :
Python:
screen pbr_test:
    frame:
        # No size specified, let the content decide of this.
        # The frame is aligned on the screen.
        xalign 0.5
        yalign 0.1

        vbox:
            #  The /vbox/ is given the size of the /frame/, since it's where the
            # The content will effectively be put.
            #  Like a container can NOT be smaller than what it contain, it will
            # also become the width of the /frame/.
            xsize 500
            #  Same for the height.
            ysize 400

            #  Now the text will be aligned on a 500 pixels wide /vbox/,
            # instead of being aligned on a /vbox/ that is of the exact size 
            # of the text.
            text "BATTLE REPORT\n":
                xalign 0.5
You should apply the style properties where they matter.
The only thing that matter for the frame is its position, so only align it. And the only thing that matter for the vbox is its size, since it's what will permit to align its content, so give the size to it ; this instead of reporting this size like your xfill True solution do.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,583
2,224
A little messing around and I've settled on this as my suggestion:

Python:
screen pbr_test:
    frame:
        ysize 400
        xalign 0.5
        yalign 0.1
        
        vbox:
            spacing 10
            xsize 500

            text "{b}BATTLE REPORT{/b}":
                xalign 0.5
                
            text "- - - - BATTLE REPORT (longer line) - - -"
            text "WIBBLE"

As Anne says, by moving the xsize and ysize to the vbox: - the vbox: is the full size in both directions and therefore the xalign on the text works how you would expect it to.

One unintended consequence is that the text is spread out vertically within the vbox:, with each text line spread out as far as possible and a huge gap between each line.

By moving the ysize back to the frame:, the frame remains full size at 500x400, but the vbox size in the y direction is the minimum needed for the text within it and avoids the massively spreading out of the text lines.

I preferred spacing 10 when I was messing, as it looked more "paragraph" like to my eyes - so I left it in.

All that said, when I tried to do something similar last night - it lost the border around the frame. I've no idea what I typed in differently last night - but I thought I'd already tried the whole "vbox within a frame" thing. And whilst it worked to an extent, it wasn't exactly the same. Go figure.
 
  • Like
Reactions: WickedCadrach

WickedCadrach

New Member
Jul 9, 2020
6
1
Thank you both! 79flavors and anne O'nymous.
I finally had a chance to get in and play around with both your suggestions and that did indeed fix things up and give me a better understanding of how to use these vboxes. Thank you both very much for your time and thorough explanations!