Using libgdx, how can I add both text and images to a ScrollPane?
Asked Answered
A

3

9

Here is a code snippet.

itemList = new List(skin, "ariel.32.white");
String[] tmpInv = new String[b+1];
tmpInv[0] = "<Empty>";
a++;
for (Entry<String, String> entry : inventoryItems.entrySet()) {
    tmpInv[a] = entry.getKey(); 
    a++;
    //String key = entry.getKey();
    //Object value = entry.getValue();
    // ...
}
Arrays.sort(tmpInv);

itemList.setItems(tmpInv);

inventoryPane  = new ScrollPane(itemList, skin);

Here is what I get, and it works fine. I'd like to add descriptive icons in front of each item but I can't seem to get it to work. I also need some way to get the name of what is selected after they are added. Currently I use

itemlist.getSelectedIndex();

Result

Apogee answered 29/6, 2014 at 20:54 Comment(0)
A
16

You can't use a list widget to add images or tables or anything other than text as far as I am aware. You can, however, make a table and change the background Drawable to a new Texture which can simulate the effect of a list when some events occur (like a mouseMove event). You can then add that table into a ScrollPane which can handle your scroll events.

This will take you a bit of coding, but here is a working example I whipped up for you:

package <some package>;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Event;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.FocusListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class ScrollScreenTest implements Screen{
    Game game;
    ScrollPane scrollpane;
    Skin skin;
    Stage stage;
    Table container, table1, table2, table3;
    Texture texture1, texture2, texture3;

    public ScrollScreenTest(Game game){
        this.game = game;
    }
    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);    //sets up the clear color (background color) of the screen.
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);  //instructs openGL to actually clear the screen to the newly set clear color.
        stage.draw();
        stage.act(delta);

    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void show() {

        // setup skin
        skin = new Skin(Gdx.files.internal("data/uiskin.json"));

        texture1 = new Texture(Gdx.files.internal("iron_axe.png"));
        texture2 = new Texture(Gdx.files.internal("iron_dagger.png"));
        texture3 = new Texture(Gdx.files.internal("iron_sword.png"));

        // table that holds the scroll pane
        container = new Table();
        container.setWidth(320f);
        container.setHeight(300f);

        // tables that hold the data you want to display
        table1 = new Table(skin);
        table1.add(new Image(texture1)).expandY().fillY();
        table1.add(new Label("", skin)).width(10f).expandY().fillY();// a spacer
        table1.add(new Label("Look at this axe I stole!", skin)).expandY().fillY();

        table2 = new Table(skin);
        table2.add(new Image(texture2)).expandY().fillY();
        table2.add(new Label("", skin)).width(10f).expandY().fillY();// a spacer
        table2.add(new Label("So dagger, much pointy.", skin)).expandY().fillY();

        table3 = new Table(skin);
        table3.add(new Image(texture3)).expandY().fillY();
        table3.add(new Label("", skin)).width(10f).expandY().fillY();// a spacer
        table3.add(new Label("Valyrian steel..", skin)).expandY().fillY();


        //inner table that is used as a makeshift list.
        Table innerContainer = new Table();
        innerContainer.add(table1).expand().fill();
        innerContainer.row();
        innerContainer.add(table2).expand().fill();
        innerContainer.row();
        innerContainer.add(table3).expand().fill();

        // create the scrollpane
        scrollpane = new ScrollPane(innerContainer);

        //add the scroll pane to the container
        container.add(scrollpane).fill().expand();

        // setup stage
        stage = new Stage();

        // add container to the stage
        stage.addActor(container);

        // setup input processor (gets clicks and stuff)
        Gdx.input.setInputProcessor(stage);

        // setup a listener for the tables with out data

        table1.addListener(new FocusListener(){
            @Override
            public boolean handle(Event event){

            if (event.toString().equals("mouseMoved")){
                table1.background(new TextureRegionDrawable(new TextureRegion(new Texture("gray.png"))));
                return false;
            }
            else if(event.toString().equals("exit")){
                //table1.setBackground(null);
                //table1.background("");
                table1.setBackground(null, false);

                return false;
            }
                return true;
            }

        });
        table2.addListener(new FocusListener(){
            @Override
            public boolean handle(Event event){

            if (event.toString().equals("mouseMoved")){
                table2.background(new TextureRegionDrawable(new TextureRegion(new Texture("gray.png"))));
                return false;
            }
            else if(event.toString().equals("exit")){
                //table1.setBackground(null);
                //table1.background("");
                table2.setBackground(null, false);

                return false;
            }
                return true;
            }

        });
        table3.addListener(new FocusListener(){
            @Override
            public boolean handle(Event event){

            if (event.toString().equals("mouseMoved")){
                table3.background(new TextureRegionDrawable(new TextureRegion(new Texture("gray.png"))));
                return false;
            }
            else if(event.toString().equals("exit")){
                //table1.setBackground(null);
                //table1.background("");
                table3.setBackground(null, false);

                return false;
            }
                return true;
            }

        });
    }

    @Override
    public void hide() {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public void dispose() {
    }

}

example

Annmarie answered 30/6, 2014 at 8:28 Comment(0)
M
3

If you want to stay with the List you could inherit the list an override the drawItem method, like this:

public class ItemList extends List<Entry<String, String>> {

    private int alignment;

    public ItemList(Skin skin, String styleName) {
        super(skin, styleName);
    }

    @Override
    protected GlyphLayout drawItem (Batch batch, BitmapFont font, int index, Entry<String, String> item, float x, float y, float width) {
        String string = toString(item);

        TextureAtlas.AtlasRegion image = // get the image, you want to draw

        batch.draw(image, x, y-image.regionHeight)

        return font.draw(batch, string, x +image.regionWidth +5, y, 0, string.length(), width -image.regionWidth -5, this.alignment, false, "...");
    }

    @Override
    public void setAlignment (int alignment) {
        this.alignment = alignment;
    }

}

With this method you do not have to reimplement the selection mechanism of the list.

Membrane answered 11/6, 2019 at 21:54 Comment(0)
S
0

So I have done this exact thing and although it might not be the best way its the only thing I could figure out. First use the Image actor for to set your image to add into the table. Then add both image and title to the table before calling row(). to get them to align correctly I was setting them as left align and then using negitive padding on the title to override the tables spacing although I'm sure theres another way. Also using get selected you can then cast it to the correct class and call getName() which you can set in any actor class so you could do it there or just call get text or something.

Sfax answered 30/6, 2014 at 4:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.