Libgdx: Table layout confusion

As someone who is quite experienced with CSS, I’m trying to understand the “table layout” which scene2d ui in libgdx uses.

However everything I do seems to yield counter-intuitive results. Like using left(), top, right, bottom whatever or width(float) and its being completely ignored
So I have this simple test code:


public class CopyOfLetsDoMenus extends ApplicationAdapter
{
   Stage stage;

    public void create ()
    {
            stage = new Stage();
            Gdx.input.setInputProcessor(stage);

            Skin skin = new Skin(Gdx.files.internal("data/uiskin.json"));
           
          Table rootTable = new Table();
          rootTable.setFillParent(true);
          rootTable.debug();
          
          Table table = new Table();
          table.debug();
          
          Label nameLabel = new Label("Name:", skin);
          TextField nameText = new TextField("ble", skin);
          Label addressLabel = new Label("Address:", skin);
          TextField addressText = new TextField("bla", skin);

          table.add(nameLabel);
          table.add(nameText).width(100);
          table.row();
          table.add(addressLabel);
          table.add(addressText).width(100);
          
          rootTable.addActor(table);
          stage.addActor(rootTable);
    }

    public void render () {
            Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            stage.act(Gdx.graphics.getDeltaTime());
            stage.draw();
            Table.drawDebug(stage);
    }

    public void resize (int width, int height) {
            stage.setViewport(width, height, true);
    }

    public boolean needsGL20 () {
            return true;
    }

    public void dispose () {
            stage.dispose();
    }
   
   public static void main(String[] args)
   {
      LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
      cfg.useGL20 = true;
      cfg.width = 480;
      cfg.height = 320;
      new LwjglApplication(new CopyOfLetsDoMenus(), cfg);
   }
}

Very short very sweet.

However, the result is this :

It seems to think the frame is twice it’s size and then center the stuff… Why ?

I’m actually just trying to follow the official guide: https://code.google.com/p/table-layout/

The TableLayout is pretty powerful, but for me it is always trial&error to get it right. If I remember correctly, I don’t use setFillParent method and do a lot of defaults

For example here is how i fight for a simple “add attribute row” :


Table attributeTable= new Table(skin);
attributeTable.setBackground(skin.getDrawable("console2"));

attributeTable.defaults().expand().fill().padBottom(4f);
attributeTable.columnDefaults(0).left();
attributeTable.columnDefaults(1).right().width(50f);
attributeTable.columnDefaults(2).right().width(40f);

label = new Label("Strength: ", skin);
attributeTable.add(label);

strLabel = new Label("", skin);
strLabel.setAlignment(Align.center, Align.center);
attributeTable.add(strLabel);

strButton = new TextButton("+", skin);
attributeTable.add(strButton);       

attributeTable.row();

add(attributeTable).expand().fill().padRight(5f);

@Cero, because of this:

rootTable.addActor(table);

This adds table as a child of rootTable using Group#addActor. The child will not be in a table cell in rootTable and won’t be laid out by rootTable. Use Table#add to add table to a table cell in rootTable.

You can make it slightly smaller:


Table rootTable = new Table().debug();
rootTable.setFillParent(true);

TextField nameText = new TextField("ble", skin);
TextField addressText = new TextField("bla", skin);

Table table = new Table(skin).debug();
table.add("Name:");
table.add(nameText).width(100).row();
table.add("Address:");
table.add(addressText).width(100);

rootTable.add(table);
stage.addActor(rootTable);

The table is given a skin, then you can create labels a little easier, since that is so common. Careful calling row() on a cell though. It can make code a little smaller but isn’t as clear where the row ends. Also row() returns the row, not the cell, so something like row().pad(5) will set the default padding for all cells in the next row.

@mojo, it shouldn’t be trial and error. Have you gone through the docs?
https://code.google.com/p/table-layout/

Cero’s example had better organization. mojo’s example mixes layout with creation, which makes it harder to read.

There is no point in using column defaults if you only have a single row. You could move right() to cell defaults, then left() on the first column. However, there is no point in using right/left at all since you are using fill(), which sizes the widget to the cell. If the widget is the size of the cell, it isn’t useful to align the widget within the cell.

Finally, I’m not sure you really need .expand().fill() since you set the width of two of the columns, but maybe you do.

// Create.

label = new Label("Strength: ", skin);

strLabel = new Label("", skin);
strLabel.setAlignment(Align.center, Align.center);

strButton = new TextButton("+", skin);

// Layout.

Table attributeTable = new Table(skin);
attributeTable.setBackground("console2");

attributeTable.defaults().expand().fill().padBottom(4f);
attributeTable.add(label);
attributeTable.add(strLabel).width(50f);
attributeTable.add(strButton).width(40f);

add(attributeTable).expand().fill().padRight(5f);

// Usually setting event listeners is next.

With this it is way easy to see your table has 3 cells in one row. I often use separate methods for create, layout, and events.

Note the setBackground(String) shortcut, since we give the table constructor a skin. Also you could use add(“labeltext”) to reduce the amount of code unless you actually need a reference to the label (eg, to change later).

@nate, yes I read all the docs :P. The code I posted is a part of an larger UI.

Great advices, I will look into it, next time I procrastinate trough refactoring :slight_smile:


http://games.frikulin.sk/images/thad_scr_05.png

I had this problem just last night. When using nested tables, make sure to expand().fill(). :slight_smile: