[lemur]when button is inside a panel,setlocaltranslation does not work

When I create a container(panel), and a button which its parent is the container, if I use button.setlocaltranslation, it does no effect on the button position.
Why is that? and how can I fix it?

here is the code I use
[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.Styles;

public class Main extends SimpleApplication {

static Main app;

public static void main(String[] args) {
    app = new Main();
    app.start();
}

@Override
public void simpleInitApp() {
    flyCam.setEnabled(false);
    GuiGlobals.initialize(this);
    Styles styles = GuiGlobals.getInstance().getStyles();
    guiFont = assetManager.loadFont("Fonts/aaa.fnt");
    Button b1 = new Button("hello");
    b1.setLocalTranslation(50, 50, 0);
    Container hudPanel = new Container("glass");
    hudPanel.setPreferredSize(new Vector3f(100,100,0));
    hudPanel.setBackground(new QuadBackgroundComponent(new ColorRGBA(0, 0.5f, 0.5f, 0.5f), 5, 5, 0.02f, false));
    hudPanel.setLocalTranslation(5, cam.getHeight() - 50, 0);
    hudPanel.addChild(b1);
    guiNode.attachChild(hudPanel);
}

}[/java]

update::
the problem is solved after I use hudPanel.attachChild(b1);

1 Like

I know you figured out a work around but I will explain what is happening anyway.

A container has a layout component by default. So any children added to the container (addChild()) will be managed by that layout. That also means the container will grow to proper size, etc. for the things that are in it. Also the children will collectively grow to fit based on how the layout is configured.

Using the normal attachChild() method (JME’s standard Node.attachChild) bypasses the layout. The two GUI elements are now essentially separate except for the parent child relationship.

Actually, I don’t have a layout component that supports absolute positions but I should probably add one for completeness.

Normally, though, a container would have lots of children organized in some way. Then a more formal layout component makes more sense because the components will lay themselves out relative to each other, etc… When you get further along and have more of an idea of what you want in this panel, I could maybe provide advice on how it could be done with a layout and not require manual positioning of the children.

1 Like
<cite>@pspeed said:</cite> I know you figured out a work around but I will explain what is happening anyway.

Thank you for the detailed explanation
I am changing my work to use lemur gui, but I got two problems, can you give me some advices?
the first problem is that, I don’t know how to hide the button or label or etc which the button’s coordinate is more or less than the height of the panel, the object always shows outside the panel but it is never to be hidden ,it can be done by setcliplayer method of tonegod gui, but I don’t know how it works in lemur gui(I have almost tried every commands inside the method but no one works)
the second problem is that I don’t know how to add commands for slider, I saw the demo example which uses the slider with VersionedReference, I don’t want to use VersionedReference, I just want to add the commands to the slider not using VersionedReference just like:
[java]
slider = new Slider(Axis.Y, “slider”){
@Override
public void ChangeValueCommand( double scale ){
do somethings

        }
    };

[/java]
is that possible to do that?

@harry1315 said: Thank you for the detailed explanation I am changing my work to use lemur gui, but I got two problems, can you give me some advices? the first problem is that, I don't know how to hide the button or label or etc which the button's coordinate is more or less than the height of the panel, the object always shows outside the panel but it is never to be hidden ,it can be done by setcliplayer method of tonegod gui, but I don't know how it works in lemur gui(I have almost tried every commands inside the method but no one works) the second problem is that I don't know how to add commands for slider, I saw the demo example which uses the slider with VersionedReference, I don't want to use VersionedReference, I just want to add the commands to the slider not using VersionedReference just like: [java] slider = new Slider(Axis.Y, "slider"){ @Override public void ChangeValueCommand( double scale ){ do somethings
        }
    };

[/java]
is that possible to do that?

Lemur tries very hard to work with standard JME materials and they don’t support clipping of the style you are talking about. So there is no way by default to clip a button to a panel… though there are many ways to make a panel automatically resize to fit a collection of buttons.

Maybe if you better describe the UI you are trying to create then I can offer advice. But a Container that contains and clips children would have to be written custom and would require custom materials on the children… or do render to texture and event passing. Neither of which are very pretty to implement.

The default slider has no event mechanism because it is more efficient to just use versioned values and generates less garbage than tons of drag events. That being said, you can easily add your own model that overrides setValue() and just catch that to do whatever you want.

[java]
public class MyModel extends DefaultRangedValueModel {
@Override
public void setValue( double d ) {
super.setValue(d);
// do stuff, fire events, whatever
}
}
[/java]

In the MVC approach, it’s often possible to have the model just talk directly to what the scroll bar will be changing… both in the value it returns and the value that gets set. In that case, if the value changes outside of slider control then you just have to make sure to update the version so that the slider updates.

Note: I took the liberty of moving this to the lemur section of the forum. I hope you don’t mind.

<cite>@pspeed said:</cite> Note: I took the liberty of moving this to the lemur section of the forum. I hope you don't mind.

Thank you for help
For clipping button or etc in lemur gui, I already solved it by myself.

here is the code I solve it, hope it can help other who wants to use lemur gui.
I am sorry for that the code has a lot of Chinese, but if you change the Chinese to English, it will work.
[java]
package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Axis;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.DefaultRangedValueModel;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Slider;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.Styles;
import java.util.Random;
import tonegod.gui.core.Screen;

public class Main extends SimpleApplication {

static Main app;

public static void main(String[] args) {
    app = new Main();
    app.start();
}
int main_Character;
int padding = 0;
Button button[] = new Button[1000];
double top = 0;
double bottom = 10;
Container panel;
Slider slider;
VersionedReference&lt;Double&gt; redRef;

@Override
public void simpleInitApp() {
    Screen screen = new Screen(this);
    guiNode.addControl(screen);
    flyCam.setEnabled(false);
    GuiGlobals.initialize(this);
    Styles styles = GuiGlobals.getInstance().getStyles();
    styles.getSelector(Slider.THUMB_ID, "slider").set("text", "[]", false);
    guiFont = assetManager.loadFont("Fonts/aaa.fnt");
    create_Name();
    panel = new Container("name");
    panel.setPreferredSize(new Vector3f(200, 300, 0));
    panel.setBackground(new QuadBackgroundComponent(new ColorRGBA(0, 0.5f, 0.5f, 0.5f), 5, 5, 0.02f, false));
    panel.setLocalTranslation(15, cam.getHeight() - 50, 0);
    slider = new Slider(new DefaultRangedValueModel(0,100,100),Axis.Y, "slider");
    redRef = slider.getModel().createReference();
    slider.setPreferredSize(new Vector3f(15, 200, 0));
    slider.setLocalTranslation(0, cam.getHeight() - 50, 0);
    for(int i=(int)top; i&lt;bottom; i++) {
            button[i] = new Button(i +":"+person_Name[i]);
            button[i].setFont(guiFont);
            panel.attachChild(button[i]);
            button[i].setLocalTranslation(0, padding, 0);
            padding -= 20;
}
    guiNode.attachChild(slider);
    guiNode.attachChild(panel);


}
String last_Name[] = new String[10000];
String first_Name = "一乙丁七乃九了二人儿入八几刀刁力匕十卜又";
String person_Name[] = new String[10000];
int name_Number_Index = 0;
int name_Index;
Random random_Number2 = new Random();

void create_Name() {
    last_Name[name_Number_Index++] = "王";
    last_Name[name_Number_Index++] = "李";
    last_Name[name_Number_Index++] = "張";
    last_Name[name_Number_Index++] = "劉";
    last_Name[name_Number_Index++] = "陳";
    last_Name[name_Number_Index++] = "楊";
    last_Name[name_Number_Index++] = "黃";
    last_Name[name_Number_Index++] = "孫";
    last_Name[name_Number_Index++] = "週";
    last_Name[name_Number_Index++] = "吳";
    last_Name[name_Number_Index++] = "徐";
    last_Name[name_Number_Index++] = "趙";
    last_Name[name_Number_Index++] = "朱";
    last_Name[name_Number_Index++] = "馬";
    last_Name[name_Number_Index++] = "胡";
    last_Name[name_Number_Index++] = "郭";
    last_Name[name_Number_Index++] = "林";
    last_Name[name_Number_Index++] = "何";
    last_Name[name_Number_Index++] = "高";
    last_Name[name_Number_Index++] = "梁";
    last_Name[name_Number_Index++] = "鄭";
    last_Name[name_Number_Index++] = "羅";
    last_Name[name_Number_Index++] = "宋";
    last_Name[name_Number_Index++] = "謝";
    last_Name[name_Number_Index++] = "唐";
    last_Name[name_Number_Index++] = "韓";
    last_Name[name_Number_Index++] = "曹";
    last_Name[name_Number_Index++] = "許";
    last_Name[name_Number_Index++] = "鄧";
    last_Name[name_Number_Index++] = "蕭";
    last_Name[name_Number_Index++] = "馮";
    last_Name[name_Number_Index++] = "曾";
    last_Name[name_Number_Index++] = "程";
    last_Name[name_Number_Index++] = "蔡";
    last_Name[name_Number_Index++] = "彭";
    last_Name[name_Number_Index++] = "潘";
    last_Name[name_Number_Index++] = "袁";
    last_Name[name_Number_Index++] = "於";
    last_Name[name_Number_Index++] = "董";
    last_Name[name_Number_Index++] = "餘";
    last_Name[name_Number_Index++] = "蘇";
    last_Name[name_Number_Index++] = "葉";
    last_Name[name_Number_Index++] = "呂";
    last_Name[name_Number_Index++] = "魏";
    last_Name[name_Number_Index++] = "蔣";
    last_Name[name_Number_Index++] = "田";
    last_Name[name_Number_Index++] = "杜";
    last_Name[name_Number_Index++] = "丁";
    last_Name[name_Number_Index++] = "沈";
    last_Name[name_Number_Index++] = "姜";
    last_Name[name_Number_Index++] = "範";
    last_Name[name_Number_Index++] = "江";
    last_Name[name_Number_Index++] = "傅";
    last_Name[name_Number_Index++] = "鐘";
    last_Name[name_Number_Index++] = "盧";
    last_Name[name_Number_Index++] = "汪";
    last_Name[name_Number_Index++] = "戴";
    last_Name[name_Number_Index++] = "崔";
    last_Name[name_Number_Index++] = "任";
    last_Name[name_Number_Index++] = "陸";
    last_Name[name_Number_Index++] = "廖";
    last_Name[name_Number_Index++] = "姚";
    last_Name[name_Number_Index++] = "方";
    last_Name[name_Number_Index++] = "金";
    last_Name[name_Number_Index++] = "邱";
    last_Name[name_Number_Index++] = "夏";
    last_Name[name_Number_Index++] = "譚";
    last_Name[name_Number_Index++] = "韋";
    last_Name[name_Number_Index++] = "賈";
    last_Name[name_Number_Index++] = "鄒";
    last_Name[name_Number_Index++] = "石";
    last_Name[name_Number_Index++] = "熊";
    last_Name[name_Number_Index++] = "孟";
    last_Name[name_Number_Index++] = "秦";
    last_Name[name_Number_Index++] = "閻";
    last_Name[name_Number_Index++] = "薛";
    last_Name[name_Number_Index++] = "侯";
    last_Name[name_Number_Index++] = "雷";
    last_Name[name_Number_Index++] = "白";
    last_Name[name_Number_Index++] = "龍";
    last_Name[name_Number_Index++] = "段";
    last_Name[name_Number_Index++] = "郝";
    last_Name[name_Number_Index++] = "孔";
    last_Name[name_Number_Index++] = "邵";
    last_Name[name_Number_Index++] = "史";
    last_Name[name_Number_Index++] = "毛";
    last_Name[name_Number_Index++] = "常";
    last_Name[name_Number_Index++] = "萬";
    last_Name[name_Number_Index++] = "顧";
    last_Name[name_Number_Index++] = "賴";
    last_Name[name_Number_Index++] = "武";
    last_Name[name_Number_Index++] = "康";
    last_Name[name_Number_Index++] = "賀";
    last_Name[name_Number_Index++] = "嚴";
    last_Name[name_Number_Index++] = "尹";
    last_Name[name_Number_Index++] = "錢";
    last_Name[name_Number_Index++] = "施";
    last_Name[name_Number_Index++] = "牛";
    last_Name[name_Number_Index++] = "洪";
    last_Name[name_Number_Index++] = "龔";
    last_Name[name_Number_Index++] = "恒";
    //more
    person_Name[0] = "關羽";
    for (int i = 1; i &lt; 99; i++) {
        name_Index = random_Number2.nextInt(20);
        person_Name[i] = last_Name[random_Number2.nextInt(name_Number_Index)] + first_Name.substring(name_Index, name_Index + 1);
    }
    person_Name[99] ="張飛";
}

@Override
public void simpleUpdate(float tpf) {
    if (redRef.update()) {
        padding = 0;
        for (int i = panel.getChildren().size()-1; i &gt;= 0; i--) {
            panel.detachChildAt(i);
        }
        panel.setBackground(new QuadBackgroundComponent(new ColorRGBA(0, 0.5f, 0.5f, 0.5f), 5, 5, 0.02f, false));
        top = 100-redRef.get()-10;
        if (top &lt; 0) {
            top = 0;
        }
        bottom = 100-redRef.get();
        if (bottom &lt; 10) {
            bottom = 10;
        }
        for (int i = (int) top; i&lt;bottom; i++) {
            button[i] = new Button(i +":"+person_Name[i]);
            button[i].setFont(guiFont);
            panel.attachChild(button[i]);
            button[i].setLocalTranslation(new Vector3f(0, padding, 0));
            padding -= 20;
        }
    }
}

}[/java]