Libgdx Table Layout Logical table not Positioning Correctly - libgdx

I wants to store a scrollpane in a table. However, the positioning of the images are not as expected.
I have look through this, but has no clue on solving my problem.
The blue box (logical table) of the scrollpane and scrolldetails table is not at the right position. Please help.
My codes goes as below:
scrollDetails = new Table();
scrollDetails.setBackground(skin.getDrawable("gameSelectionBox1"));
scrollDetails.setDebug(true);
Button b = new Button(skin,"arithmetic");
scrollDetails.add(b);
scrollDetails.pack();
sp = new ScrollPane(scrollDetails);
sp.setOverscroll(false,true);
sp.pack();
sp.setDebug(true);
table = new Table();
table.setFillParent(true);
table.bottom().padBottom(100).add(sp).align(Align.center);
table.setDebug(true);
table.pack();
//tried but has no effect
//t.setPosition(0,100);
//sp.setPosition(0,550);
//tt.setPosition(0,100);
stage.addActor(tt);

setFillParent() does not work correctly inside a ScrollPane. Remove the line and it will work as intended.

Related

Scene2d Positioning Components on Stack

This is current state: image
But there are 2 more things I want to do:
moving the stack to the top left of the screen
In the image, I divided the parchment into two parts, I want to put 2 labels on the upper part and 2-3 text buttons on the lower part.
related codes:
Table table = new Table();
table.center();
table.setFillParent(true);
Stack stack = new Stack();
titleLabel.setFontScale(0.5f);
label1.setFontScale(0.5f);
textButton.getLabel().setFontScale(0.5f);
textButton2.getLabel().setFontScale(0.5f);
parchment.setScaling(Scaling.fill);
stack.add(parchment);
Table overlay = new Table();
overlay.add(titleLabel).expand();
overlay.row();
overlay.add(label1).expand();
overlay.row();
overlay.add(textButton).expand();
overlay.row();
overlay.add(textButton2).expand();
stack.add(overlay);
table.add(stack).top().left();
stage.addActor(table);
The first thing to do in situations like this is to set debug on any tables you have - you will then be able to see the boundary lines showing how big the table is and how big the cells in the tables are. Simply do this:
table.setDebug(true);
moving the stack to the top left of the screen
With debug set, I can see that your stack isn't filling the whole table or the whole screen. Stacks only grow to fit their contents, they will not fill the their container automatically, so to fill the screen add "expand()" to the Stack's cell in the Table like this:
table.add(stack).expand().top().left();
In the image, I divided the parchment into two parts, I want to put 2 labels on the upper part and 2-3 text buttons on the lower part.
You can do this in one of two ways. You could make a table for each group which would be a good approach if there are lots of items in each group. Or if there are only a few items you can add "expand()" to force the items in the middle to push the other items up/down, like this:
Table table = new Table();
// table.setDebug(true);
table.setFillParent(true);
Stack stack = new Stack();
titleLabel.setFontScale(0.5f);
label1.setFontScale(0.5f);
textButton.getLabel().setFontScale(0.5f);
textButton2.getLabel().setFontScale(0.5f);
parchment.setScaling(Scaling.fill);
stack.add(parchment);
Table overlay = new Table();
// overlay.setDebug(true);
overlay.add(titleLabel).top();
overlay.row();
overlay.add(label1).expand().top();
overlay.row();
overlay.add(textButton).expand().bottom();
overlay.row();
overlay.add(textButton2).bottom();
stack.add(overlay);
table.add(stack).expand().top().left();
stage.addActor(table);

Add horizontal scroll Libgdx

I want to design my levels on a horizontal pane what i am doing is:
container = new Table(skin);
container.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
levelselect = new Table(skin);
levelselect.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
// list = new List(skin,"1");
scrollPane = new ScrollPane(levelselect);
scrollPane.layout();
levelselect.align(Align.left);
for(int i=1;i<20;i++){
levelnumber = new Label(" "+i,levelnumbertext);
levelselect.add(levelnumber);
}
container.align(Align.bottom);
container.add(scrollPane).width(400).height(400);
container.add(levelselect);
any suggestions?? thanks in advance.
Using a ScrollPane and Table for this sounds like a lot of unnecessary overhead, they have a lot going on in the background, dynamically calculating their own layouts etc, you might not need this if you just want a full screen side scroller. You might be best just positioning your Actors on the Stage, however far along they need to be and update the Camera position to suit. Stage has culling options which I think by default are enabled, so it won't be drawing any of your Actors that are off the screen.

Libgdx Can you set the bounds of a ScrollPane?

So recently i discovered Scrollpanes and have been trying implement one properly.
After a bit of searching i found this section of code
public void create() {
batch = new SpriteBatch();
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
stage = new Stage();
gamelog = new Label("Start", skin);
gamelog.setAlignment(Align.center);
gamelog.setWrap(true);
Table scrollTable = new Table();
scrollTable.add(gamelog);
scrollTable.row();
scroller = new ScrollPane(scrollTable);
Table table = new Table();
table.setFillParent(true);
table.add(scroller).fill().expand();
Now for the most part this code works well. a scrollpane is actually created and i can dynamically add text to it. my issue however is the size of the scrollpane takes up the whole screen, and initial text is centered in the middle of the scrollpane(so in the middle of the screen) and only starts to scroll once enough text has been added to take up the whole height of the screen.
Rather than expanding on its own what i actually want is for the scrollpane to take up just a small section at the bottom of the screen.
I have tried setting the bounds of the tables and of the scrollpane but the closest i have come is merely moving the scrollpane downwards(meaning the last text added is off screen and not in view. Its s if it completely ignores any width or height set and just expands on its own.
I figure i could get the desired effect by simply using a set of labels at the bottom of the screen and change their text dynamically but then the scroll feature would be lost. so before i do this i was hoping someone could shed some light on wether or not it is possible to resize and set a scrollpanes bounds?
Table uses cells to size its components. When you add a component to a table it returns the table's cell which holds that component. You can then use the cell to set the size of the component.
In your original code try this:
table.add(scroller).size(460, 200);
And if you want to change the scrollpane size after adding it to the table, you can get the cell from the table and then set its size like this:
table.add(scroller);
...
table.getCell(scroller).size(460, 200);
And here is the API for Cell:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/ui/Cell.html
I stumbled across a solution with trial and error.
the following code works for me and allows the scrollpane to be resized and positioned. The main culprit seems to be the use of table.setFillParent(true); and the order in which you try to set the parent tables bounds.
batch = new SpriteBatch();
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
stage = new Stage();
gamelog = new Label("Start", skin);
gamelog.setAlignment(Align.center);
gamelog.setWrap(true);
Table scrollTable = new Table();
scrollTable.add(gamelog);
scrollTable.row();
scroller = new ScrollPane(scrollTable);
Table table = new Table();
table.setBounds(10, 10, 460, 200);
table.add(scroller).fill().expand();
scrollTable.debug();
scroller.debug();
table.debug();
stage.addActor(table);

Force an actor to obey the width set in table.add(actor).width()

I am setting the width of actor in table.add(actor).width(width). The padding is set to 1% of screen width. This is the result I get:
As you can see, spacing between actors is way beyond 1% . I tried using fill() methods but it didn't work. I also tried setFillParent(true) on the actor, no success. What is going on here? This is the complete code. The only spacing between actors should be the one I set with padding. How do I achieve this?
private void createScrollPane(){
texture=new Texture("badlogic.jpg");
ImageButton.ImageButtonStyle fibs=new ImageButton.ImageButtonStyle();
fibs.imageUp=new TextureRegionDrawable(new TextureRegion(texture));
button1= new ImageButton(fibs);
button2= new ImageButton(fibs);
button3= new ImageButton(fibs);
button1.setPosition(0, 0);
button2.setPosition(0, 0);
button3.setPosition(0, 0);
scrollTable=new Table();
scrollTable.setBounds(Gdx.graphics.getWidth()*0.03f,0,Gdx.graphics.getWidth()*0.94f, Gdx.graphics.getHeight());
scrollTable.setPosition(Gdx.graphics.getWidth() * 0.03f, 50);
scrollTable.add(button1).width(Gdx.graphics.getWidth() * 0.3f).padLeft(Gdx.graphics.getWidth() * 0.01f).fill();
scrollTable.add(button2).width(Gdx.graphics.getWidth() * 0.3f).padLeft(Gdx.graphics.getWidth() * 0.01f).padRight(Gdx.graphics.getWidth() * 0.01f).fillX();
scrollTable.add(button3).width(Gdx.graphics.getWidth() * 0.3f).padRight(Gdx.graphics.getWidth() * 0.01f).fill();
stage.addActor(scrollTable);
}
ImageButton is a Button with an Image on top of it. If you just want a button then use the Button class and set the up drawable to the drawable you want it to be. Note that you can enable debug drawing of the stage or table to visualize what is going on.
Your function calls are affecting the Table's cells, not the actors in the cells.
Call scrollTable.setDebug(true) to see the cells, padding, etc. You'll be happy to find your function calls are working, just on the cells rather than their contents.
The next step is to build a composite layout with widgets which allow you to expand the buttons but maintain them in a horizontal alignment. You might be able to accomplish that with just a table if you battle the cells hard enough, I'm not sure.
What I did was to use a Table, then add a HorizontalGroup. The HorizontalGroup goes within a cell on the Table. Inside the HorizontalGroup I add my buttons. Laying out the buttons the way I want within the HorizontalGroup is far easier than doing it via the Table.
For an ImageButton you can explicitly set the minHeight and minWidth of the style, which will forcibly scale the attached Image.

How to align table in scrollPane top?

I' am making achievements screen in my libgdx game. I want to align my table in scrollPane to top, now it is centred vertically and horizontally and I don't know why. Using .top() method when I've tried to create new row didn't worked.
stage = new Stage();
Gdx.input.setInputProcessor(stage);
outerTable = new Table();
innerTable = new Table();
innerTable.setFillParent(true);
for(int i=0;i<score_bound; i++){
if(i<score_state){
innerTable.row().width(achie_width).height(achie_height).top();
innerTable.add(new Image(ltm.assets.score_textures[i]));
}else{
innerTable.row().width(achie_width).height(achie_height).top();
innerTable.stack(new Image(ltm.assets.score_textures[i]),new Image(ltm.assets.kurtyna));
}
}
for(int i=0;i<letin_bound; i++){
if(i<letin_state){
innerTable.row().width(achie_width).height(achie_height).top();
innerTable.add(new Image(ltm.assets.letin_textures[i]));
}else{
innerTable.row().width(achie_width).height(achie_height).top();
innerTable.stack(new Image(ltm.assets.letin_textures[i]),new Image(ltm.assets.kurtyna));
}
}
scrollPane = new ScrollPane(innerTable);
outerTable.setPosition(0, 0);
outerTable.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
outerTable.debug();
outerTable.add(scrollPane).fill().expand();
stage.addActor(outerTable);
I run into the same issue today and came across here, so I might as well post an answer here in case somebody is still looking for an answer.
#peterSweter said top() does not work, what #Rara suggested is the same as calling top.
The only way to achieve something that looks like an align to the top - which only is relevant if the innerTable is smaller - is to increase the size by adding empty elements around it, so the table you pass to the ScrollPane has at least the same size as the scrollPane.
I just wrapped yet another Table around my innerTable reference.
(658 is the fixed height I use for my ScrollPane)
Table spacingTable = new Table();
spacingTable.setHeight(Math.max(innerTable.getHeight(), 658));
spacingTable.add(innerTable);
if (innerTable.getHeight() < 658) {
spacingTable.row();
spacingTable.add().expandY();
}
ScrollPane scroll = new ScrollPane(spacingTable, skin);
In order to achieve what you want, you can wrap your table inside another table and use that table for ScrollPane. Note that when adding your table to container table, you'll need to add some growable, empty cell at the bottom and right side in order to "push" it to top-left (although I believe you can also simply use containerTable.add(myTable).top().left() - but haven't tested it really).
This of course is a much better solution than second's solution, which uses hardcoded height. The thing is, you will usually want to add scroll pane as growable (.grow()), so fixed height/width is useless.