java - 更改 JLabel 的文本,其中文本是另一个类中的统计信息

标签 java class jlabel

我正在制作一款游戏,该游戏有一个可以在其中花费游戏币的商店。我想显示您必须花费的硬币数量。该值随着游戏的进行而不断变化。我有能力显示初始值并随着购买而变化,但它不会从其他类更新。

这是我的代码:

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/

相关文章:

java - 如何从资源中引用xml文件? eclipse

java - 列出未知枚举的值

c++ - 使用 DLL 覆盖/修改 C++ 类

java - 控制 HTML JLabel 的重新验证

java - 用于 Java 的 Finagle Thrift 生成器

cmd上的java编译问题(json简单)

java - java中JFrame输入错误时通知用户

java - 重新验证 JPanel 时闪烁

java - 迭代优先级队列抛出 ConcurrentModificationException

c++ - 如何为具有私有(private)对象作为属性的类编写移动构造函数和赋值运算符?