Ren'Py Screen hbox vbox for a character profile

Playstorepers

Member
May 24, 2020
160
79
Hey there, everyone.



I'm trying to find a clever solution for the arrangement of text in screens for a character profile.

I found a very convoluted solution and I am very intrigued and positive, that there must be a smarter implementation.

What I basically want is this:


Python:
#Box which has the information on the character
frame:
    area (520, 180, 1350, 790)
    viewport:
        scrollbars "vertical"
        mousewheel True
        draggable True

        hbox:
            vbox:
                spacing 20
                text "Nickname: " xalign 1.0
                text "Birthday: " xalign 1.0
                text "Additional information/rumors: \n" xalign 1.0
                text " " xalign 1.0
                text "Character: " xalign 1.0
                text " " xalign 1.0
            vbox:
                spacing 20
                text "Test"
                text "01.01.2000"
                text "Really long ass text, that has information on Test, but is so long, that it need another line"
                text "Another short information"
                text "Stupid"
                text "Nice"
The hbox has two vboxes:
vbox 1 has the title of the information (name, birthday, whatever)
vbox 2 has the information for that specific character (Test, 01.01.2000)

So in the end we get a nice screen with:

name: Test
Birthday: 01.01.2000
Additional information/rumors: Really long ass text, that has information on Test, but is so long, that it need another line"
etc.

with the title of the information being on the right of the vbox right next to the corresponding information.

Sadly, that implementation makes use of \n for longer texts and is therefore quite unelegant.

Another problem, that occurs, is that in the mobile version for example, the font size changes, which then breaks the entire screen with crooked boxes etc., because some texts, that were short enough in the pc-version fit to fit in one line, now suddenly becomes two lines, due to the increased fontsize.

So I'm basically looking for a solution, that doesn't involve \n in those texts.

So I tried this:


Python:
frame:
    area (520, 180, 1350, 790)
    viewport:
        scrollbars "vertical"
        mousewheel True
        draggable True

        vbox:
            spacing 20
            hbox:
                text "Nickname: "
                text "Test2"
            hbox:
                text "Birthday: "
                text "01.01.2000"
            hbox:
                text "Character: "
                vbox:
                    text "Stupid"
                    text "Nice"

That's also working okayish. However, each hbox now is always aligned on the left and the unity of the first example is missing (The one, where you could insert xalign 1.0)

Does anyone got an elegant solution?
Because I could use method 1 and adjust it for the mobile version, but I think, that there must be an elegant solution here, that I have overlooked.

Thanks in advance.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
I hate screen: language.

But I had to have a try. Maybe someone can come up with something more elegant, but this seems to work how you planned...

Edit: I managed something a lot more elegant a few posts further down.

Python:
screen char_info():
    modal True
    style_prefix "charinfo"

    frame:
        pos (220, 180)
        xysize (1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            vbox:
                hbox:
                    vbox style "charinfo_col1":
                        text "Nickname:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Test"

                hbox:
                    vbox style "charinfo_col1":
                        text "Birthday:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "01.01.2000"

                hbox:
                    vbox style "charinfo_col1":
                        text "Additional information/rumors:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Really long ass text, that has information on Test, but is so long, that it need another line"
                        #text "small"

                hbox:
                    vbox style "charinfo_col1":
                        text "" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Another short information"

                hbox:
                    vbox style "charinfo_col1":
                        text "Character:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Stupid"

                hbox:
                    vbox style "charinfo_col1":
                        text "" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Nice"

style charinfo_vbox:
    spacing 20

style charinfo_hbox:
    spacing 20

style charinfo_col1:
    xsize 530

style charinfo_col2:
    xsize 800

My first thought was grid:, but each cell of the grid is made the same size in each direction. Therefore the huge size of that line means the "headings" column would be the same size. Likewise, when I finally managed to get the text to wordwrap, all the rows became bigger to match too.

I then looked at xmaximum. Which got me part the way there.
Then I decided to try to make the columns fixed width, using both xmaximum and xminimum (they can be combined using simply xsize).

I got a bit confused, since I couldn't really control the size of the text lines. So I ended up wrapping those in another vbox (that might be unnecessary).

Then, rather than code the same parameters over and over again, I moved them to style: definitions.

It works, but it still feels like a kludge.
 
Last edited:
  • Like
Reactions: Playstorepers
Apr 24, 2020
192
257
Initially I was going to say "just use xminimum" to force a size for the hboxes in your second try but for some unknown reason the boxes still end up with different lengths, which makes no sense to me.

Grid was my second guess, after realizing it exists, but this just uses the size of the largest box for everything else, which looks absolutely ridiculous.

So at the moment I'm just as confused.
 
  • Like
Reactions: Playstorepers
Apr 24, 2020
192
257
In my own version of an information screen I just admitted defeat and stacked things vertically.

Name and birthday never change, so they can just get stacked on each other with the character traits going at the bottom.
The additional information will be completely unpredictable, so I would just let that have its own box to play around with.

Python:
screen test:
    frame:
        area (520, 180, 1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            hbox:
                vbox:
                    xsize 300
                    label "Nickname: "
                    text "Test"
                    text ""
                    label "Birthday: "
                    text "01.01.2000"
                    text ""
                    label "Character: "
                    text "Stupid\nNice"
              
                vbox:
                    label "Additional information/rumors:"
                    text ""
                    text "Really long ass text, that has information on Test, but is so long, that it need another line. Another short information"
Again, not an elegant solution, but it's presentable.
 
  • Like
Reactions: 79flavors

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
There may be a solution using textbutton instead of text, as buttons seem more controllable with regards to their sizing. Not all buttons need an action and without the action and the appropriate styling, it would just look like any other text.

I like the idea of using label instead of text in there too by InCompleteController. That at least would allow for the xalign = 1.0 parameters to be moved to a common style.
 
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
Thanks for the quick answers, you two and yeah, it's kinda confusing, for being such a simple problem, which is why I was positive, that there would be a more elegant solution somewhere.

And grid was also one idea, that I had, but grid forces the field to split in half, which is not my intention, since I wanted to have the xpos of the information positioned depending on the largest xpos of the titles.




I hate screen: language.

But I had to have a try. Maybe someone can come up with something more elegant, but this seems to work how you planned...

Python:
screen char_info():
    modal True
    style_prefix "charinfo"

    frame:
        pos (220, 180)
        xysize (1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            vbox:
                hbox:
                    vbox style "charinfo_col1":
                        text "Nickname:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Test"

                hbox:
                    vbox style "charinfo_col1":
                        text "Birthday:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "01.01.2000"

                hbox:
                    vbox style "charinfo_col1":
                        text "Additional information/rumors:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Really long ass text, that has information on Test, but is so long, that it need another line"
                        #text "small"

                hbox:
                    vbox style "charinfo_col1":
                        text "" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Another short information"

                hbox:
                    vbox style "charinfo_col1":
                        text "Character:" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Stupid"

                hbox:
                    vbox style "charinfo_col1":
                        text "" xalign 1.0
                    vbox style "charinfo_col2":
                        text "Nice"

style charinfo_vbox:
    spacing 20

style charinfo_hbox:
    spacing 20

style charinfo_col1:
    xsize 530

style charinfo_col2:
    xsize 800

My first thought was grid:, but each cell of the grid is made the same size in each direction. Therefore the huge size of that line means the "headings" column would be the same size. Likewise, when I finally managed to get the text to wordwrap, all the rows became bigger to match too.

I then looked at xmaximum. Which got me part the way there.
Then I decided to try to make the columns fixed width, using both xmaximum and xminimum (they can be combined using simply xsize).

I got a bit confused, since I couldn't really control the size of the text lines. So I ended up wrapping those in another vbox (that might be unnecessary).

Then, rather than code the same parameters over and over again, I moved them to style: definitions.

It works, but it still feels like a kludge.


This one is better than mine but still struggles with the problem, that there is some space on the left unused, because of the forced xsize. The ideal scenario would be, if we could determine the maximum size for charinfocol1, which would be varying because of the different fontsize and because of different title tags (e.g. Some characters don't have Additional information/rumors, which is a pretty "long" text).

But thanks for the impulse, it's a lot better than my idea and if worse comes to worst I can just change the styles depending on mobile, pc or title tags.




In my own version of an information screen I just admitted defeat and stacked things vertically.

Name and birthday never change, so they can just get stacked on each other with the character traits going at the bottom.
The additional information will be completely unpredictable, so I would just let that have its own box to play around with.


Python:
screen test:
    frame:
        area (520, 180, 1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            hbox:
                spacing 200
                vbox:
                    label "Nickname: "
                    text "Test"
                    text ""
                    label "Birthday: "
                    text "01.01.2000"
                    text ""
                    label "Character: "
                    text "Stupid\nNice"
              
                vbox:
                    label "Additional information/rumors:"
                    text ""
                    text "Really long ass text, that has information on Test, but is so long, that it need another line. Another short information"
Again, not an elegant solution, but it's presentable.
This one on the other hand is kinda an accepted defeat and just a "Do it differently", but you're absolutely right: That's one way to implement it.
 

Playstorepers

Member
May 24, 2020
160
79
I must confess, its just a lazy way of not having to create a style when I want to have a category stand out from the main text. Some day it's going to bite me hard.
I feel you, brother.

But you're with me, when I always say:
TODAY'S NOT THE DAY!

But yeah, one day it will come back to bite me in the ass too.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
Okay. I think I finally got there...

Python:
screen char_info():
    modal True
    style_prefix "charinfo"

    frame:
        pos (220, 180)
        xysize (1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            vbox:
                hbox:
                    label "Nickname:"
                    text "Test"

                hbox:
                    label "Birthday:"
                    text "01.01.2000"

                hbox:
                    label "Additional information/rumors:"
                    text "Really long ass text, that has information on Test, but is so long, that it need another line"
                    #text "small"

                hbox:
                    label ""
                    text "Another short information"

                hbox:
                    label "Character:"
                    text "Stupid"

                hbox:
                    label ""
                    text "Nice"

style charinfo_vbox:
    spacing 20

style charinfo_hbox:
    spacing 20

style charinfo_label:
    xsize 560

style charinfo_label_text:
    xalign 1.0
    color "#9999FF"

style charinfo_text:
    xmaximum 790
    color "#FFFFFF"

Just adjust the style xsize values to match your preferred sizing.

Edit:
To clarify... apparently label is a window containing text. Both the window and the text can have separate styles applied to them. So style charinfo_label is the window portion and style charinfo_label_text is the text portion.

Oh lordy, I'm learning so much about styles today. ;-)
 
Last edited:

Playstorepers

Member
May 24, 2020
160
79
Okay. I think I finally got there...

Python:
screen char_info():
    modal True
    style_prefix "charinfo"

    frame:
        pos (220, 180)
        xysize (1350, 790)
        viewport:
            scrollbars "vertical"
            mousewheel True
            draggable True

            vbox:
                hbox:
                    label "Nickname:"
                    text "Test"

                hbox:
                    label "Birthday:"
                    text "01.01.2000"

                hbox:
                    label "Additional information/rumors:"
                    text "Really long ass text, that has information on Test, but is so long, that it need another line"
                    #text "small"

                hbox:
                    label ""
                    text "Another short information"

                hbox:
                    label "Character:"
                    text "Stupid"

                hbox:
                    label ""
                    text "Nice"

style charinfo_vbox:
    spacing 20

style charinfo_hbox:
    spacing 20

style charinfo_label:
    xsize 560

style charinfo_label_text:
    xalign 1.0
    color "#9999FF"

style charinfo_text:
    xmaximum 790
    color "#FFFFFF"

Just adjust the style xsize values to match your preferred sizing.

Dammit you beat me to it, but I would suggest one change:


Python:
screen char_info():

    modal True

    style_prefix "charinfo"


    frame:

        pos (220, 180)

        xysize (1350, 790)

        viewport:

            scrollbars "vertical"

            mousewheel True

            draggable True


            vbox:

                hbox:

                    label "Nickname:"

                    text "Test"


                hbox:

                    label "Birthday:"

                    text "01.01.2000"


                hbox:

                    label "Additional information/rumors:"
                  
                    vbox:
                      
                        text "Really long ass text, that has information on Test, but is so long, that it need another line"

                        text "Another short information"


                hbox:

                    label "Character:"
                  
                    vbox:

                        text "Stupid"

                        text "Nice"


style charinfo_vbox:

    spacing 20


style charinfo_hbox:

    spacing 20


style charinfo_label:

    xsize 560


style charinfo_label_text:

    xalign 1.0

    color "#9999FF"


And one addendum:
This shitty thing works too, if necessary:


Python:
if renpy.variant("pc") or (renpy.variant("web") and not renpy.variant("mobile")):
    style charinfo_col1:
        spacing 20
        xsize 530
else:
    style charinfo_col1:
        spacing 20
        xsize 630
But in this case you can just create a new style family and add your if-clauses to grab a different style family depending on your needs.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,359
15,270
Again, not an elegant solution, but it's presentable.
Yet it's the most elegant solution. You limit the size of the column, what will limit the size of the text displayed inside.

There no reason to apply the limit somewhere else, it should always be done on the most outer part. It's what permit to have the smoother result, since it's Ren'py itself that will decide if, when, and how, an inner part's size have to be treated.