我正在制作一款游戏,该游戏有一个可以在其中花费游戏币的商店。我想显示您必须花费的硬币数量。该值随着游戏的进行而不断变化。我有能力显示初始值并随着购买而变化,但它不会从其他类更新。
这是我的代码:
public StoreFrame(Run game,You y) {
super("Store");
theGame=game;
setLayout(null);
you=y;
try {
storeBack = ImageIO.read(new File("backgrounds/store.png"));
}
catch (IOException e) {
}
//background
setContentPane(new JLabel(new ImageIcon(storeBack)));
coins = new JLabel("Coins: "+you.gettotCoins());//here is the problem
coins.setFont(new Font("SanSerif", Font.BOLD, 18));
coins.setForeground(Color.black);
coins.setBounds(25, 25, 100, 100);
add(coins);
setSize (800,600);
setResizable(false);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
}
文本来自的类:
public class You {
private int totCoins;
public You(int p) {
totCoins=110;//starting money
}
public int gettotCoins() {
return totCoins;
}
public void settotCoins(int subtract) {
totCoins-=subtract;
}
}
请帮忙
最佳答案
因为使用设计模式是一种很好的做法,所以您可以考虑使用观察者模式。这个想法是创建一个接口(interface),定义一个(或多个)方法,当需要更新某些内容时可以调用这些方法。所有对更新感兴趣的类都可以实现此接口(interface),并且更新的主题会保留这些观察者的列表。
就您而言,这意味着您可以定义一个 CoinObserver
接口(interface)(尝试使用有意义的名称),如下所示:
public interface CoinObserver {
void coinsChanged(int newAmount);
}
接下来,需要将监听器列表保存在存储您的硬币数量的地方。因为我假设这是在 You
类中,所以使用观察者模式,您的类将如下所示:
public class You {
private int totCoins;
private Collection<CoinObserver> coinObservers;
public You(int p) {
totCoins=110;
coinObservers = new ArrayList<>(); //or any collection you like
}
public int getTotCoins() {
return totCoins;
}
//Setters turn out to be very useful in this case if used correctly
private void setTotCoins(int newCoins) {
totCoins = newCoins;
coinsChanged();
}
public void subtractCoins(int subtract) {
setTotCoins(totCoins - subtract);
}
public void addCoinObserver(CoinObserver co) {
coinObservers.add(co);
}
public void removeCoinObserver(CoinObserver co) {
coinObservers.remove(co);
}
private void coinsChanged() {
for(CoinObserver co : coinObservers) {
co.coinsChanged(getTotCoins());
}
}
}
最后,您必须为您的货币扩展 JLabel
来实现此接口(interface),如下所示,并让它“订阅”自己作为 CoinObserver
:
public class CoinLabel extends JLabel implements CoinObserver {
public CoinLabel(You you) {
super("Coins: " + you.getTotCoins());
setFont(new Font("SanSerif", Font.BOLD, 18));
setForeground(Color.black);
setBounds(25, 25, 100, 100);
you.addCoinObserver(this);
}
@Override
public void coinsChanged(int newAmount) {
setText("Coins: " + newAmount);
}
}
请注意,此解决方案将聚集大量观察者,因为它们永远不会从您
身上消失。这可以通过覆盖 dispose()
方法来解决,但是您应该使用 setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
(尽管我对此并不完全确定)并且为 You
保留一个字段,以便在构造函数之外使用它。
按照您的建议调用 setText("Coins: "+ you.getTotCoins())
方法可能看起来需要做很多工作,但如果您的代码开始变得更加复杂。一些主要优点可能是:
- 自动化:每次更改硬币数量时,您不需要考虑编写
label.setText("...")
,因为每次为硬币设置了新值,观察者将收到通知。 - 可扩展性:假设您想要制作某种百分比栏来指示您拥有的最大可能金额的多少。您不必在金额可能发生变化的地方一遍又一遍地绘制条形图,只需将条形图设为
CoinObserver
,并实现coinsChanged(int newAmount)
方法即可并将其添加到观察者列表中,无需对现有代码进行任何更改。 - 松散耦合:如果您的目标是低耦合,观察者模式可确保您实际上不需要了解 GUI 中的
You
类(您只需要观察者接口(interface),即addCoinObserver(co)
和removeCoinObserver(co)
)。此外,您的You
类永远不会知道观察者到底是什么,它只知道CoinObserver
的接口(interface)。这允许针对 MVC model 进行编程这通常是很好的做法。
而且可能还有更多。我想在这里指出的最后一件事是:如果您只在一个地方更改硬币的值(value),并且您不太可能对其他地方的硬币感兴趣,那么您不应该使用观察者模式。设计模式可以在所有可能的方面为您提供帮助,但不应过度使用它们。
关于java - 更改 JLabel 的文本,其中文本是另一个类中的统计信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30792464/