Adding content to containers - sizes, margins

ricodricod Posts: 13Member
edited May 10 in GUI

First, I'm really new to Control nodes like Containers. So far I've only done the step by step tutorial of the docs.

main problem : I don't understand the behavior of control nodes, how changing some settings auto changes others

Trying to achieve : Panel that shows the base palette of an image with labels like name, percentage of total, etc. Dynamically filled, so panel needs to shrink and grow based on content.

test setup scene tree:
(root) Node2D with script

  • AnimatedSprite node
  • instanced PalettePanel scene

PalettePanel scene tree (attached):
(root) Panel, full rect layout, x position offset so it always appears on the right side of the sprite. size:

  • MarginContainer, center layout, anchors are all 0.5, custom constatns : 4 pixels margins all sides
  • HBoxContainer, I want 2 columns at the moment : color rects on the left, percentage labels on the right
  • 2 VSplitContainers. This is where a lot happens that I don't get, mainly because I duplicate the color rect and label depending on the amount of unique colors of the sprite.
  • first has a color rect, second a label with dynamic font resource

Script (haven't touched panel yet, focusing on the columns right now) :

var palette = get_color_palette(frame0.get_data(), 0) # dictionary.
    var keys = palette.keys() # Colors
    var values = palette.values() # integers, amount of pixels with that color
    var total = 0.0
    for val in values:
        total += val
    var y = 0
    var cr := $Panel/MarginContainer/HBoxContainer/VSplitContainer/ColorRect
    var lbl := $Panel/MarginContainer/HBoxContainer/VSplitContainer2/Label
    var v_container2 = $Panel/MarginContainer/HBoxContainer/VSplitContainer2
    cr.rect_size = Vector2(16, 3)
    for key in keys:
        if y == 0:
            cr.color = key
            var val : int= palette.get(key)
            var percentage : float = (val / total) * 100
            lbl.text = str(round(percentage)) + "%"
            lbl.rect_position = Vector2(0, y * 4)
        else:
            var crdup := cr.duplicate()
            crdup.color = key
            crdup.rect_position = Vector2(0, y * 4)
            var lbldup := lbl.duplicate()
            var val : int= palette.get(key)
            var percentage : float = (val / total) * 100
            lbldup.text = str(round(percentage)) + "%"
            lbldup.rect_position = Vector2(0, y * 4)
            v_container.add_child(crdup)
            v_container2.add_child(lbldup)
        y += 1!

Now, it does this:

The problem mainly seems to be that first duplicate. I tried adding : crdup.rect_size = Vector2(16, 3), but it ignores it.
Is there some kind of best practice I'm unaware of ? Likem when adding content to a container, update this or that. I tried going up the inheritance tree in the docs from the vsplitcontainer to control node, but am probably missing it.

Best Answer

  • MegalomaniakMegalomaniak Posts: 2,618
    Accepted Answer

    Ah, aren't H/VSplitContainers the ones that create a movable divider(aka dragger)? I thinks it's the VBoxContainer you are looking for.

Answers

  • MegalomaniakMegalomaniak Posts: 2,618Admin

    Edited the post formatting for readability.

  • ricodricod Posts: 13Member

    ow nice, thnx! I don't see any tags to get that code markup. How can I mark code for formatting?

  • MegalomaniakMegalomaniak Posts: 2,618Admin
    edited May 10

    multiple lines indented by at least 2 spaces become a code block:


    like
        this
    

    but you could also place ~~~ one line above and one line below a code block.

      like
        this
    

    The indentation way requires careful control of the surrounding lines, in the first example I had to use horizontal separators via --- on their own lines to make it work. Quoting this post should let you see it in editor.

  • MegalomaniakMegalomaniak Posts: 2,618Admin

    Hmm, the script attached to your Node2D is what is controlling this instanced PalettePanel scene? I'd probably give the PalettePanel it's own script and define a palette_panel class name for it in there.

  • ricodricod Posts: 13Member

    Thanks!

    So, I put the script on the root node of the GUI scene (the Panel) and put it in an update_panel () method with the palette Dictionary as parameter. Then I call that method from the Node2D script and pass the Dictionary with the palette data, but the result is the same.

    The first duplicated ColorRect takes the entire height of the Panel it seems. All the following duplicates are 3 px, as assigned. When I print the rect size, and a bunch of other properties to a text file right after duplicating, it states (16,3) for all 6 duplicates. I'm currently going through all variables, but they all look the same to me. The labels seem a bit weird to me too. I printed a bunch of variables to a text file and I see this:

    child: [Label:1357] <- first one
    rect_size: (16, 4.5) <- height is 5 in Inspector, why is it 4.5 now?
    rect_min_size: (16, 0)
    marg_t: 0
    marg_b: 4.5 <- same thing, states 5 in Inspector
    rect_scale: (1, 1)
    s_flags_v: 4
    child: [Label:7397] <- first duplicate
    rect_size: (16, 14) **<- height of 14 pixels ? **
    rect_min_size: (16, 0)
    marg_t: 5
    marg_b: 19
    rect_scale: (1, 1)
    s_flags_v: 4

    all the following labels are like the last one, but with increaing top and bottom margins of 5 pixels per row.

    I did found out that when I uncheck Size Flags : Vertical Fill on the Color Rect, the second Color Rect (the first duplicate one) no longer fills the entire area, but the strange spacing remains.

  • ricodricod Posts: 13Member
    edited May 10

    I guess it has something to do with Panel, VSplitContainer, MarginContainer or any of the layout settings.

    • When I add the color rects as children of Panel (root node), they neatly align, except for the second. It hugs the top one, instead of leaving a 1 pixel gap, like the rest. Then there's a 2 pixel gap between the second and third. But only if I set the minimum height to be 4, just like rect_size height. If the minimum is 0, the actual height is 0, even though rect_size reads 4 when printing it.
    • When I add them as children of MarginContainer I see the last one, completely filling the entire inner area of the MarginContainer
    • When I add them as children of the HBoxContainer they neatly align horizontally, equally spaced. But with some unexplained offset on the X-axis
    • When I add them as children of either of the VSplitContainers the weird bug with the second Color Rect is back.
    • When I make the VSplitContainer the root, reset the layout and then add the ColorRects, I still get that weird placement / size issue. Tried having empty Containers and generating the ColorRects dynamically, from scratch. Same issue.
    • When I change the VSplitContainer into something else, like an ItemPanel, they space as expected.

      :s Guess I'm staying away from VSplitContainers for a while

  • MegalomaniakMegalomaniak Posts: 2,618Admin
    Accepted Answer

    Ah, aren't H/VSplitContainers the ones that create a movable divider(aka dragger)? I thinks it's the VBoxContainer you are looking for.

  • ricodricod Posts: 13Member

    :o Argh! Yes, the VBoxContainer works like a charm! Thanks Megalomaniak!
    I'm going to rock back and forth in a corner for a bit.

  • MegalomaniakMegalomaniak Posts: 2,618Admin

    Eh, I've made the mistake and used a VSplit in place of a VBox before myself. It happens... ;)

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file