I've been working on some app's using libgdx & I can't figure out how to position a button via coords.
public void create() {
batch = game.getSpriteBatch();
background = new Texture("data/textures/menuScreen_small.png");
bubbleArray = new Array<Bubble>();
Gdx.input.setInputProcessor(stage);
for (int i = 0; i < 20; i++) {
bubbleArray.add(new Bubble(MathUtils.random(0,
Gdx.graphics.getWidth()), MathUtils.random(0,
Gdx.graphics.getHeight())));
}
table = new Table();
stage.addActor(table);
table.setSize(1280, 720);
table.setPosition(0, 0);
//table.left().top();
// table.debug();
//table.row().minHeight(55).maxHeight(55);
skin = new Skin(Gdx.files.internal("data/ui/uiskin.json"));
/*
* HomeScreen [Button 1]
*/
final TextButton camButton = new TextButton("Camera", skin);
//Add button
table.add(camButton);//.left().expandX().fillX();
camButton.setPosition(0, 0);
//Button Height
//table.row().minHeight(55).maxHeight(55);
//Button Width
//table.row().minWidth(55).maxWidth(55);
In the code above I am trying to position my textButton "camButton" at 0,0 on the screen.
when I start the program it's in the very center of the screen.
If anyone has some guides or tips let me know, I need to learn this stuff.
a small 'fix'
Not exactly a fix; but by removing the table in general solved this problem. By doing this I'm adding it to the stage instead of stage > table > button. Any comments to that?
If you just want to be able to fix buttons to absolute positions like 0,0 there is no need to add the items to a table, just add you button to the stage
TextButton button = new TextButton("Floating Button", skin);
button.setPosition(10, 10);
stage.addActor(button);
Edit
If you still want the controlled positioning that the table provides check out the guide for the table layout it has many good examples Table Layout
If you want to position the table
table.left().bottom();
To position items inside a table
table.add(button).expand().bottom().right();
I had your problem. My requirement for the whole screen or part of the screen was. I solved my problem using WidgetGroup layout.
actor.setPosition(100,200);
yourWidgetGroup.addActor(actor);
Related
In libgdx I have a ScrollPane in my application and I can't figure out how to get it to scroll without extra space at the top. Currently, there is a massive space at the top of the pane, and when I scroll down, the text (high scores) slowly fill up the space.
BEFORE SCROLLING:
AFTER SCROLLING:
Is it possible to start without the space (so the pane is completely filled) and when I scroll, I can scroll through the high scores without them moving upwards?
I noticed I can accomplish this by removing the following line.
table.setTransform(true);
But if I do this, I cannot scale or set origin on the table so the text appears too large.
Below is my scrollpane creation method:
private void createScrollPane(ArrayList<String> scrollPaneScores) {
scrollPaneViewport = new FitViewport(800, 480);
stage = new Stage(scrollPaneViewport);
Skin skin = new Skin(Gdx.files.internal("skin/uiskin.json"));
Table scrollableTable = new Table();
scrollableTable.setFillParent(true);
stage.addActor(scrollableTable);
Table table = new Table();
for (String score : scrollPaneScores) {
table.add(new TextButton(score, skin)).row();
}
table.pack();
table.setTransform(true);
//table.setTransform(true); //clipping enabled ... this setting makes scrolling not occur in uniform fashion
table.setOrigin(400, 0);
table.setScale(0.75f);
final ScrollPane scroll = new ScrollPane(table, skin);
//scrollableTable.add(scroll).expand().fill();
scrollableTable.add(scroll).maxHeight(300);
//stage.setDebugAll(true);
//When stage is created, set input processor to be a multiplexer to look at both screen and stage controls
inputMultiplexer.addProcessor(inputProcessorScreen);
inputMultiplexer.addProcessor(stage);
Gdx.input.setInputProcessor(inputMultiplexer);
scrollPaneCreated = true;
}
Remove the setFillParent line. It is an old problem with tables inside scrollpanes.
Try removing the scrollableTable.setFillParent(true);
What I'm trying to do is add a label to follow a slider knob and display the knob's value. I currently have a vertical slider and a label stacked inside a table cell. I'm able to position the label to where the knob is and update it's text correctly but am having a problem while moving the knob.
When I move the knob I can make the label follow it as long as I don't update the text. But if I update the text then the label re-centers itself in the cell till the knob has stopped moving at which point it places itself on the knob.
How do I make it so that the label doesn't reposition while it's updating text?
Here's some sample code of what I have going on:
public class OptionsWindow implements Screen {
private Stage stage;
private Table table;
private Slider slider;
private Label label;
private Skin textSkin = new Skin(Gdx.files.internal("skins/skin.json"),
new TextureAtlas(Gdx.files.internal("skins/text.pack")));
private Skin sliderSkin = new Skin(Gdx.files.internal("skins/skin.json"),
new TextureAtlas(Gdx.files.internal("skins/text.pack")));
private min = 1, max = 2;
#Override
public void show() {
stage = new Stage();
table = new Table();
slider = new Slider(min, max, 0.001f, true, sliderSkin);
label = new Label(""), textSkin);
table.stack(label, slider).height(1000);
table.setFillParent(true);
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
label.setY(slider.getValue() - min);
label.setText(slider.getValue());
stage.act();
stage.draw();
}
}
I've done a lot of searching for an answer to this question but have yielded no results. I have also tried placing the label in a container and moving the container while changing the label text, but the same result happens. I'm sure somebody had done this before. It seems like something people would want. Please, any help is welcome.
Never done it before, I always show the amount in a label next to or above the slider to give feedback. But the result you are after gives a nice touch. Did you try adding a ChangeListener to your slider? Everytime the slider changes this would be called. So if you insert the new position and text in there it should be updating correctly.
//Slider has to be "final" for the listener.
final Slider slider = new Slider(0, 10, 1, true, skin);
slider.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
label.setY(slider.getValue() - min);
label.setText(slider.getValue());
}
});
This does not need to be in your render method. It's a listener so whenever something happens the listener listens for it will execute.
Ok, so I came up with a work around. It would seem that labels move back to their cell alignment position while updating text. to solve this I simply placed my label in a table with a row on either side like so:
Table subTable = new Table();
subTable.add().row();
subTable.add(label).row();
subTable.add();
Then in render I calculate new height values for the exterior cells and apply them:
float topH, botH;
// Calculate heights
topH = (1 - slider.getPercent()) * parentTable.getHeight();
botH = slider.getPercent() * parentTable.getHeight();
// Apply heights to exterior table cells
subTable.getCells().get(0).height(topH);
subTable.getCells().get(2).height(botH);
// Update label text
label.setText(slider.getValue());
This is just a simple form of what I have. You'll want to take into account the label height to get it to position correctly. Also if you want it to follow with the slider at the slider's set animateDuration, you'll want to use getVisualPercent() instead of getPercent(). However this causes issues when your finger flies out of the cell. For some reason the visual percent is linked to where the slider knob is when your finger leaves the cell, not where it ends up.
My work around for this was to just set the animateDuration to 0.0f and just use getPercent(). If I or someone comes up with a solution to the getVisualPercent() option, then that would be nice to have posted as well.
I'm trying to make a shop for my game.
In this shop, there should be 2 scroll pannel : one with your iventory's stuff, the other one with what the dealer sells.
(It 'd like to make it this way)
http://i.stack.imgur.com/5gLUr.jpg
So at first, I tried to put a list in my ScrollPane, but I can't put both image of my weapons and text in those.
So I tried to put a table in my ScrollPane : as long as I have stuff in my inventory, I add cells with the item's texture, another one with the name of the weapon, ...)
But there's no way I found to select the table ...
So I'm a bit confused : if I use a List, I can't put texture and make it look fancy, but with Tables, I can't select the items ...
Have you guys got any ideas of how I should do that ?
Thanks !
EDIT : Here is some code, but no everything since it's pretty ugly !
Table test3 = new Table(skin2);
for(WeaponElement weapon : GameScreen.dataLoader.getWeaponArray()){
Image img = new Image(new Texture(weapon.getIconPath()));
test3.add(img).width(32);
test3.add().width(10);
test3.add(weapon.getName()).align(Align.left).row();
}
panelShop = new ScrollPane(test3, skin2);
panelShop.layout();
So basically, I add all my weapons into my test3 table rows add it into my ScrollPane, but i'd like to make them selectable, with I can do by using lists but if I do so, I can't use anymore tables to make it look great...
What about using Buttons to push? The example below shows a table with one button a row. Use a Button with the text you want to display and add a picture beside it.
Table scrollableTable = new Table(skin);
scrollableTable.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
for(WeaponElement weapon : GameScreen.dataLoader.getWeaponArray()){
final TextButton button = new TextButton(wapon.name, skin, "default");
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
// do stuff
});
scrollableTable.add(button).center();
// add a picture
Image img = new Image(new Texture(weapon.getIconPath()));
scrollableTable.add(img).width(32);
// finish a row
scrollableTable.row();
}
Try Tree ui component and use it as table. It is selectable and accepts Actor as node (use Table as row layout).
See com.badlogic.gdx.tests.TestTree (link) example.
I'm making a lobby in a multi-player game, which may have any number of players displayed in a table. I have the following code:
camera = new OrthographicCamera(WIDTH,HEIGHT);
camera.position.set(WIDTH/2,HEIGHT/2, 0);
camera.update();
stage = new Stage();
Gdx.input.setInputProcessor(stage);
stage.setCamera(camera);
stage.setViewport(WIDTH,HEIGHT,false);
ScrollPaneStyle paneStyle = new ScrollPaneStyle();
paneStyle.background = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("cavebg"));
paneStyle.vScrollKnob = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("GUI/slidernob"));
paneStyle.hScroll = paneStyle.hScrollKnob = paneStyle.vScroll = paneStyle.vScrollKnob;
Table container = new Table();
table = new Table();
ScrollPane pane = new ScrollPane(table,paneStyle);
container.add(pane).width(WIDTH).height(HEIGHT);
container.row();
container.setBounds(0,0,WIDTH,HEIGHT);
stage.addActor(container);
font = new BitmapFont();
color = new Color(0,0,0,1);
style = new TextButtonStyle();
style.font = font;
style.up = new TextureRegionDrawable(WizardsDuel.atlas.findRegion("GUI/guibg"));
style.fontColor = color;
handler = new ChangeHandler();
ArrayList<User> users = FirebaseManager.lobbyUsers;
for(int i = 0; i < users.size() || i < 100; i++){
TextButton tmp = new TextButton("",style);
tmp.scale(2);
//tmp.setText(users.get(i).name);
tmp.setText(i+ " asdf");
tmp.addListener(handler);
table.add(tmp).width(WIDTH/4f);
if(i%2 == 1 && i > 0)
table.row();
}
Despite the manner in which the table clearly extends below the bottom of the screen(which should be the bottom of the scroll pane), there is no scroll bar, and clicking and dragging does nothing.
Screenshot:
maybe you forget to make stage act in render(), add something like:
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
}
You do actually need two things. An outer Container and an inner Container. You do regularly use two Tables for this. So here is a small example how I use the scrollPane. Actually with no style but it should make it clear.
this.table = new Table();
this.container = new Table();
scroll = new ScrollPane(table);
container.add(scroll).width(500f).height(500f);
container.row();
The table is the table one where you do add the stuff that should be scrollable. The container is the outer box. So you can add for example a headline above your scrollbox. The outer box (container) does need a size. Else you will not have any scrollbars or such. And you do need the inner table.
Simple example for adding:
style = new LabelStyle(font, Color.WHITE);
label = new Label(null, style);
table.add(label);
table.row();
label.setAlignment(1); // align center
give it more lines that it can show and you'll have a scroll pane. Else there is no scrollbar or such.
All in one. You just missed the outer container i think. Add it and it should work. Don't forget to sett the sizes.
My problem was that is wasn't receiving input. My I shouldn't have set the input processor in the constructor, because, the previous screen was setting the processor to null when it was "hidden", so when I moved the line to LobbyScreen's show method it happened after the previous screen was hidden, and the input is set correctly.
after you init the scrollpane you should call this first
mScrollPane.layout();
2023 | KOTLIN
The element to be scrolled must be added to the stage or group before passing it to the ScrollPane
Create the necessary actor and add it to the stage or group
val actor = Actor()
[Stage/Group].addActor(actor)
Create a ScrollPane and place an actor in it
val scrollPane = ScrollPane(actor)
Set the position and dimensions for the actor and the ScrollPane
actor.setBounds(x,y,w,h) | scrollPane.setBounds(x,y,w,h)
PS. Vel_daN: Love what You DO 💚.
I have a horizontal panel with 3 buttons: Back, Next and Cancel. I've made horizontal alignment to the right, but only Next and Cancel buttons follow this alignment.
Here is the code:
HorizontalPanel buttons = new HorizontalPanel();
buttons.setWidth("100%");
cancel = new Button("Cancel");
next = new Button("Next");
back = new Button("Back");
buttons.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
buttons.add(back);
buttons.setCellWidth(back, "98%");
buttons.add(nextBtn);
buttons.setCellWidth(next, "1%");
buttons.add(cancel);
buttons.setCellWidth(cancel, "1%");
The problem is with this panel width. But if I delete it, all my buttons are left aligned. As a workaround I can use false button, that will be invisible and has cell width = 97%, the cell width of back button is 1%. But this is not what I need, because inspite of small amount of memory this invisible button consumes, it is still a memory :)
What is going wrong with this alignment? Maybe something is wrong with panel width? Hope for your help, thank you in advance.
There is setCellHorizontalAlignment() property in HorizontalPanel. With it you can give alignment to its widgets.
Try following:
buttons.setCellHorizontalAlignment(backButton, HasHorizontalAlignment.ALIGN_RIGHT);
buttons.setCellHorizontalAlignment(nextButton, HasHorizontalAlignment.ALIGN_RIGHT);
buttons.setCellHorizontalAlignment(cancelButton, HasHorizontalAlignment.ALIGN_RIGHT);
You can achieve this much easier using css:
FlowPanel panel = new FlowPanel();
panel.setWidth("100%");
cancel = new Button("Cancel");
cancel.getElement().getStyle().setFloat(Float.RIGHT);
next = new Button("Next");
next.getElement().getStyle().setFloat(Float.RIGHT);
back = new Button("Back");
back.getElement().getStyle().setFloat(Float.RIGHT);
panel.add(back);
panel.add(nextBtn);
panel.add(cancel);