Reputation: 105
Having an issue with tables and updating a label! Here is the dilemma, I have a sell button in my game that is updating the player's coins whenever they sell an item, that part is working perfectly. The issue I am having is trying to get the coin value to update on the screen while there in this separate menu (see pic attached, coins in the top left). The problem is that the coin value is in another stage in another class. This is because I have different tables that pop up in the middle when I click the different buttons at the bottom. I have tried helper methods for going in and clearing that table and updating it and then sending me back to this item page but it is not working, I can post any code needed but this is more of a general question on how to update a label within a table in a stage.
Update: So to kinda sum up my question, I have a Screen and I have have three tables in it the bottom table the top left and the top right. Then I add the table to the stage in the middle when they press the inventory or shop button etc. What I am looking to do is to keep the item page open and simply just update the value of the Coin label, I know I can change the text using .setText(); Im just not sure how I can update that portion of the screen etc..
Update 2: If I just set the screen back to a new screen of this screen it updates the coin value but then I am not on the item page anymore which is not ideal.
Update 3: Thanks for the help so far guys, @John your answer is super helpful aswell. Im still not getting this working though here is a little bit of the code where the label is being handled.
playerCoinLabel = new Label(playerSave.getCoinsString(),skin,"defaultMiddle");
This is where it is getting added to the table.
tableLeft = new Table(skin);
stage.addActor(tableLeft);
tableLeft.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableLeft.setFillParent(true);
tableLeft.top().left();
tableLeft.add(healthNonButton).size(84,80).left().padLeft(10).padTop(5);
tableLeft.add(playerHealthLabel).left().padLeft(15);
tableLeft.row();
tableLeft.add(levelNonButton).size(74,70).center().padLeft(10);
tableLeft.add(playerLevelLabel).left().padLeft(19);
tableLeft.row();
tableLeft.add(coinNonButton).size(74,70).center().padLeft(10);
tableLeft.add(this.playerCoinLabel).left().padLeft(15); //This line
tableLeft.row();
Then I have this method for updating my label using the setText like you guys were telling me about.
public void updatePlayerCoins() {
playerCoinLabel.setText(playerSave.getCoinsString());
}
and if I call this method anywhere, render() or where im setting the new coin value it is not updating/changing the label in the top left of my screen. I can post all the code to a github if I need to just posted the things involving the label. This is just a project im working on to increase my skill set so sorry if I sound amateur, it is because I am!
Thanks everyone!
Upvotes: 0
Views: 2302
Reputation: 1490
It seems like you're asking two things- how do I update a label? and How do I structure my code? It's hard to tell what's going wrong with the former since we can't see your code, but @Tenfour04 is right- you want to retain a reference to the label somewhere and call setText()
when you want to change the amount.
As far as structuring your code, I would suggest a simple OOP design and then evolve it like so:
First, we need an object to represent the player:
class Player {
private int coins; // Pretend there are getters / setters.
private int health;
private int level;
}
Now you probably have more than one way that you want to represent this player information, so we'll split the rendering code into a separate class or set of classes:
class StatWidget {
private Stage stage;
private Player player;
private Label lblCoins;
public StatWidget(Player player) { // Pseudo-code
this.player = player;
this.stage = new Stage();
Table tbl = new Table();
this.lblCoins = new Label(); // Notice we keep a reference to the label
tbl.add( this.coins );
}
public void update() {
lblCoins.setText(player.getCoins());
}
}
Now you can sync the UI with your player object's state simply by calling Player#update()
. But when do you call it?
You could call update()
in your render method. This is a little inefficient because you're updating the object whether it needs to be updated or not, but it's dead simple, and if you're only updating a few UI elements this way it probably doesn't matter. Personally, I'd stop here.
If you want to be more precise, you would only call update()
when you actually make a change to the Player's coins. You can do this by finding the places in your code where you set the player's coins and add the update call like so:
player.setCoins( A_LOT_OF_MONEY );
statWidget.update();
Problem is this gets more cumbersome as you add more widgets- all your game logic now has to know about StatWidget and make calls to it. We could cut this dependency a little bit by using an event-driven architecture. Essentially, whenever player's state changes, it would send an event to interested parties notifying them of the change. You could use the pseudo-code below:
interface Publisher {
void subscribe(Subscriber subby);
void unsubscribe(Subscriber subby);
}
class Player implements Publisher {
private List<Subscriber> subscribers;
private int coins;
// ...
public void setCoins(int amount) {
this.coins = amount;
for(Subscriber subscriber : subscribers) subscriber.notify("COINS", amount);
}
public void subscribe(Subscriber subby) {
this.subscribers.add(subby);
}
public void unsubscribe(Subscriber subby) {
this.subscribers.remove(subby);
}
}
interface Subscriber {
void notify(String event, int qty);
void dispose();
}
class StatWidget implements Subscriber {
private Publisher player;
private Label label;
// ...
public StatWidget(Player player) {
this.player = player;
this.player.addSubscriber(this);
void notify(String event, int qty) {
if(event.equals("COINS")) label.setText(qty);
}
void dispose() {
this.player.unsubscribe(this);
}
}
The event system above could certainly be polished, and you could likely do clever things with generics (or use a library that has thought all this out for your), but hopefully it illustrates the concepts.
Upvotes: 2