How to make a centered label with Icon?

I’d like to make a lemur Label with this layout

The padding marked in red should be the same on both sides, so that the label+icon is always centered regardless of text width.

Thanks for the help!

Set the label up with the icon aligned right and the text aligned left.

Then use a DynamicInsetsComponent as your insets component to center it.

If the label has a background then set the background to the label’s border and put the insets component as the background.

2 Likes
    label.setTextHAlignment(HAlignment.Left);
    label.setIconHAlignment(...);
          ^^^^^^^^^^^^^^^^^ don't exist

Icon class don’t exist either. I can just set a Icon which is a GuiComponent and don’t know how to use :frowning:

Have you not run across the IconComponent before?

…I thought from your first post that you already knew how to add an icon to a label.

label.setIcon(new IconComponent());

…and IconComponent has alignments on it.

1 Like

Ok thanks! But still don’t know how to attach all this stuff to a Node:

class My extends Node{
//...
    iconComponent = new IconComponent(icon);
    label.setIcon(iconComponent);
    label.setTextHAlignment(HAlignment.Left);
    iconComponent.setHAlignment(HAlignment.Right);
    DynamicInsetsComponent dic = new DynamicInsetsComponent(5, 5, 5, 5);
    attachChild(label); // ...mmh?
    attachChild(dic);  //nope
    dic.attach(label);  //no way

Have you used Lemur before? You may want to go through the getting started stuff to know how to attach a Label to a node. (Hint: node.attach(label))

As I said in the earlier post, you would set the dynamic insets component as the insets of the label.

…but I get the feeling that maybe I don’t really know what you are trying to do?

Sorry, I meant “how to set the insets for the label” (I assumed that DynamicInsetsComponent worked like a Spatial and therefore should somehow be attachable to a Node)

    DynamicInsetsComponent dic = new DynamicInsetsComponent(5, 5, 5, 5);
    label.setInsets(dic); //nope
    dic.attach(label);  //no way

http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Panel.html#setInsetsComponent(com.simsilica.lemur.component.InsetsComponent)

Edit: FYI, setInsets() is just a convenience method that calls setInsetsComponent(new InsetsComponent(insets)) internally.

1 Like

Well… text and icon placement is ok but it doesn’t look very centered

This is the code

    label.setLocalTranslation(0, 63, 0);
    label.setFont(myFont);
    label.setFontSize(35);
    label.setTextVAlignment(VAlignment.Center);
    label.setTextHAlignment(HAlignment.Center);
    label.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
    iconComponent = new IconComponent(icon);
    label.setIcon(iconComponent);
    label.setTextHAlignment(HAlignment.Left);
    iconComponent.setVAlignment(VAlignment.Center);
    iconComponent.setHAlignment(HAlignment.Right);
    DynamicInsetsComponent dic = new DynamicInsetsComponent(5, 5, 900, 900);
    label.setInsetsComponent(dic);

a) if you are managing the position yourself then you will also have to manage the size also. Or just put the labels in a container.

b) your dynamic insets values are very strange. If you want something centered then just set all of the values to 0.5… which will give each side half the available extra space. In your case, you’ve told it that the top and left should have 5/905s of the available space and the right and bottom should have 900/905s of the available space.

Waitwhat. Since when does anything aside from addChild and jme’s attachChild exist?

I meant attachChild().

But I misunderstood what he was asking anyway.

A Container for each label, yes? But still not there… I suspect that this would be super easy if I were to only use Lemur components, but since I’m mixing in Nodes then I miss some automagical functionality…

    Container c = new Container();
    c.setLocalTranslation(0, 63, 0);
    label.setFont(myFont);
    label.setFontSize(35);
    label.setTextVAlignment(VAlignment.Center);
    label.setTextHAlignment(HAlignment.Center);
    label.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
    iconComponent = new IconComponent(icon);
    label.setIcon(iconComponent);
    label.setTextHAlignment(HAlignment.Left);
    iconComponent.setVAlignment(VAlignment.Center);
    iconComponent.setHAlignment(HAlignment.Right);
    DynamicInsetsComponent dic = new DynamicInsetsComponent((float) 0.5, (float) 0.5, (float) 0.5, (float) 0.5);
    label.setInsetsComponent(dic);
    c.addChild(label);
    attachChild(c);

You do not need a container for each label. I’m just not sure why there isn’t a parent container for all of the labels. That part hasn’t been explained and your screen shot makes me think it’s the way it should be.

If the labels are not in a container then you need to set the size yourself else they will just default to their preferred size… which is of course just whatever their no-padded size would be. So if you want them all to be 500 wide or whatever then set their size to 500 wide. Then the dynamic insets will do its thing.

Or just put them all in one parent container and set its size to 500 wide.

Edit: PS:

DynamicInsetsComponent dic = new DynamicInsetsComponent(0.5f, 0.5f, 0.5f, 0.5f);
…saves a bunch of typing.

Thanks, I’ll probably switch to Containers (layout is on a different class, and used on several places so I need to refactor things), but for now I think you mean this, which still don’t do what I want:

    label.setLocalTranslation(0, 63, 0);
    label.setPreferredSize(new Vector3f(500, 50, 0));
    label.setFont(myFont);
    label.setFontSize(35);
    label.setTextVAlignment(VAlignment.Center);
    label.setTextHAlignment(HAlignment.Center);
    label.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
    iconComponent = new IconComponent(icon);
    label.setIcon(iconComponent);
    label.setTextHAlignment(HAlignment.Left);
    iconComponent.setVAlignment(VAlignment.Center);
    iconComponent.setHAlignment(HAlignment.Right);
    DynamicInsetsComponent dic = new DynamicInsetsComponent(0.5f, 0.5f, 0.5f, 0.5f);
    label.setInsetsComponent(dic);
    attachChild(label);

Text is on the left, icon on the right with a big gap in the middle. Size is right tough.

label.setSize(new Vector3f(500, 50, 0));

…but you may have to do it after you attach it. I can’t remember for sure.

Forcing the preferred size prevents calculating the preferred size, I think… and that may cause issues.

Yes, if I do it before attaching I get a crash because Bound is not set. However, this code give me everything aligned to the left (like on the screenshot above):

    label.setLocalTranslation(0, 63, 0);
    label.setFont(myFont);
    label.setFontSize(35);
    label.setTextVAlignment(VAlignment.Center);
    label.setTextHAlignment(HAlignment.Center);
    label.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
    iconComponent = new IconComponent(icon);
    label.setIcon(iconComponent);
    label.setTextHAlignment(HAlignment.Left);
    iconComponent.setVAlignment(VAlignment.Center);
    iconComponent.setHAlignment(HAlignment.Right);
    DynamicInsetsComponent dic = new DynamicInsetsComponent(0.5f, 0.5f, 0.5f, 0.5f);
    label.setInsetsComponent(dic);
    attachChild(label);
    label.setSize(new Vector3f(500, 50, 0));

Could you please take a look? Thanks! :slight_smile:

I’m not sure when I will get to try the code myself.

In the mean time, you could try putting them all in one Container and seeing if that fixes the issue.

IllegalArgumentException: Child is not GUI element.

Indeed, it is a Node which contains:
-3 quads for the background
-the Label/Icon.
-it has a mouselistener for mouseover/click

Actually, it’s more like a button.

Should I extend GuiElement, or Label, or Button?