Lemur Textfield Background

Hello. Here’s another Lemur question.

I have been trying to add a background in the groovy style sheet. but it won’t show …

Any clues?

Turns out anything attached to a panel doesn’t get a background?

Am I doing something wrong? I need to use a panel instead of a Container because I want to have absolute positioning for the children.

I would have to see styles, code, etc. to comment. Anything can have a background whether in a container or not.

If you are using addChild() on a panel with no layout then the child won’t get laid out… so it will be 0,0,0 in size as far as backgrounds and stuff are concerned.

If you want absolute positioning for the children then you have a few choices depending on how you want the parent to act. It would save me time if you explain what you are actually trying to make happen and then I won’t have to tell you five different approaches that don’t matter.

    Panel c = new Panel(400, 300);
    c.setLocalTranslation(500, 500, -1);
    guiNode.attachChild(c);
    
    TextField text = new TextField("dfgdfgdfg", new ElementId("textField"));
    text.setLocalTranslation(100, -100, 1);
    c.attachChild(text);

I’ve got the positioning down. I need the TextField to have the background I set in the style code.

def skin = TbtQuadBackgroundComponent.create( 
texture( name:"Interface/border.png", generateMips:false),
1, 3, 3, 4, 5, 1f, false); 

selector( "panel", "nimble" ) {
    background = skin.clone()
}

selector( "textField", "nimble" ) {
    background = skin.clone()
}

Panel with TextField attached looks like this, the text is a TextField with missing background.

Does the text field have a style if you don’t add it to the panel? Is “nimble” your default style?

What is likely happening is that your text field is never getting layed out so it thinks its size 0,0,0. BitmapText isn’t clipped so it will render anyway.

If that’s the case then you might need to textField.setSize(textField.getPreferredSize()). When GUI elements are “attached” as children of another GUI element sometimes they get confused about whether they should size themselves or not.

Sweeeeeet!

textField.setSize(textField.getPreferredSize()) worked.

If you find you will be positioning a lot of children this way then you might save some trouble by adding an intermediate node to the panel.

myPanel.attachChild(someNode);
someNode.attachChild(myTextField);

…then I believe the text field will autosize itself.

When they are direct parent and child then some assumptions are made (that are usually valid) about how and when the child will be managed. With the intermediate node, that ‘feature’ should be negated.

While I have you is it possible to make a TbtQuadBackgroundComponent from a type of textureatlas. I want to keep all my ui skins in one texture.

Maybe add in a start point and end point to the constructor for the region of the texture to create the ninepatch?

Also is there a way to button.setTextHAlignment(HAlignment.Center) in the groovy style sheets?
I don’t want to have to do this for every button.

Yes:
textHAlignment=HAlignment.Center

…you just have to make sure to import the HAlignment class.

Yeah, it’s actually on my short-term to-do list to do this for a regular quad component. I can probably also make a Tbt version pretty easily.

If you want to watch paint dry:

i have the problem
how i put a background in textfield and passwordfield

By setting the background.

What have you tried? What didn’t work? What’s the code look like?

this is my code
package mygame;

import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
import com.jme3.math.*;
import com.jme3.scene.*;

import com.simsilica.lemur.*;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.style.ElementId;


public class LoginState extends BaseAppState {

    private Container loginPanel;
    private TextField nameField;
    private PasswordField passwordfield;

    public LoginState() {
    }
 
    protected void join() {
        
        String name = nameField.getText().trim();
        if( getState(ConnectionState.class).join(nameField.getText(),passwordfield.getText()) ) {
            getStateManager().detach(this);
        }
    } 
       protected void options(){
  getStateManager().attach(new OptionsState());
        
        // Disable ourselves
        setEnabled(false);
 
 } 
    protected void cancel() {
        getState(ConnectionState.class).disconnect();
        getStateManager().detach(this);
    }
    
    @Override   
    protected void initialize( Application app ) {
        loginPanel = new Container();
        loginPanel.addChild(new Label("Server", new ElementId("title")));
        
        Container props = loginPanel.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X, FillMode.None, FillMode.Last)));
        props.setBackground(null);        
        props.addChild(new Label("Username:"));
        nameField = props.addChild(new TextField(System.getProperty("user.name")), 1);
        props.addChild(new Label("Password:"));
        passwordfield=props.addChild(new PasswordField(System.getProperty("Pass.word")), 1);
        Container buttons = loginPanel.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
        buttons.setBackground(null);
        buttons.setLayout(new SpringGridLayout(Axis.X, Axis.Y));
       buttons.addChild(new ActionButton(new CallMethodAction("Login", this, "join"))); 
      buttons.addChild(new ActionButton(new CallMethodAction("Registar", this, "join")));
     buttons.addChild(new ActionButton(new CallMethodAction("Opcoes", this, "options")));
       buttons.addChild(new ActionButton(new CallMethodAction("Cancel", this, "cancel")));
        
        float scale = 1.5f * getState(MainMenuState.class).getStandardScale();
        loginPanel.setLocalScale(scale);
        
        Vector3f prefs = loginPanel.getPreferredSize().clone();
        prefs.x = Math.max(300, prefs.x);
        loginPanel.setPreferredSize(prefs.clone());
        
        // Now account for scaling
        prefs.multLocal(scale);
        
        int width = app.getCamera().getWidth();
        int height = app.getCamera().getHeight();
        
        loginPanel.setLocalTranslation(width * 0.5f - prefs.x * 0.5f, height * 0.5f + prefs.y * 0.5f, 10);       
    }
 
    @Override   
    protected void cleanup( Application app ) {
    }
    
    @Override   
    protected void onEnable() {
        Node root = ((Main)getApplication()).getGuiNode();
        root.attachChild(loginPanel);
    }
 
    @Override   
    protected void onDisable() {
        loginPanel.removeFromParent();
    }
}

I’m trying to understand what the issue is. Have you tried setting a background on passwordField? That would be the quickest way to set the background on passwordField.

i want put a border
but this is my result

The border is based on the background image. You can create a background image with a transparent inner and a white border. Then can set the background color to set the border color.

You can also set a separate border component:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Panel.html#setBorder(com.simsilica.lemur.core.GuiComponent)

…it works essentially like the background, though. It’s just “behind” the background, so to speak.

Edit: the point is that nowhere in your code do you actually call passwordField.setBackground()… so of course it doesn’t have a different background than the default. You’d have to set the background if you want to set the background. Or set the border if you want to set the border.

If you don’t set the background then the background won’t be set.

i can´t make work
can make a example

I can’t see code.

examples all over codebase.

Setting the background of a TextField is exactly like setting the background of anything else.

someGuiElement.setBackground(yourBackgroundComponent);

What is is that you have a problem with?

i solve the problem
with this code

[CODE]
GuiComponent username= user.getBackground();
GuiComponent password= pass.getBackground();
nameField = props.addChild(new TextField(""), 1);
GuiComponent username= user.getBackground();
GuiComponent password= pass.getBackground();
nameField.setBorder(username);
nameField.setBackground(username);
passwordfield=props.addChild(new PasswordField(""), 1);
passwordfield.setBorder(password);
passwordfield.setBackground(password);

[CODE]

Setting this to both doesn’t make any sense.

I just don’t understand what is so hard about:

passwordField.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));

…or whatever.

But if you want to copy the backgrounds from some other fields, that’s fine, too. But setting the border and the background is a waste.