有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何根据另一个类更改状态更新进度条?

我目前正在开发一款游戏,我正在尝试实现一个健康栏,它将在玩家每次受到伤害时更新,我目前已将其设置为在布局中的单独面板中:

// menu is the bit with the health bar
ControlPanel menu = new ControlPanel(this);
window.add(menu.getMainPanel(), BorderLayout.NORTH);
// view is the part of the window the game runs in
window.add(view, BorderLayout.CENTER);

我听说要使其更新,您可以使用changelistener,但要使其正常运行,我遇到了一些困难,到目前为止,我得到的是:

private JProgressBar healthProgressBar;
private Player player;

public ControlPanel(Game game) {
    player = game.getPlayer();

    healthProgressBar.setString(player.getHealth() + "/100");
    healthProgressBar.setStringPainted(true);
    healthProgressBar.setValue(player.getHealth());
    healthProgressBar.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            int oldHealth = player.getHealth();
            player = (Player) e.getSource();
            if (player.getHealth() != oldHealth) {
                healthProgressBar.setValue(player.getHealth());
            }
        }
    });

public JPanel getMainPanel() {
    return mainPanel;
}

它将使进度条显示在我想要的地方,并且它将具有我赋予它的值,但是当玩家受到伤害时它不会更新,如果有人知道如何使其工作,那将非常感谢


共 (1) 个答案

  1. # 1 楼答案

    好的,这是一个有点冗长的答案,但我只想展示一个使用侦听器来允许松散耦合和更新JProgressBar的示例

    假设您有一个非GUI播放器对象,它有一个String name属性和一个int health属性,并使用属性更改支持来允许添加侦听器。此类的一个片段可能如下所示:

    class Player {
        public static final String HEALTH = "health"; // the name of the property of interest
        public static final int HEALTH_MIN = 0;
        public static final int HEALTH_MAX = 100;
        private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
        private String name;
        int health = 50; // value from 1 to 100
    
        public Player(String name) {
            this.name = name;
        }
    
        public int getHealth() {
            return health;
        }
    
        // any time this is called, listeners will be notified through the pcSupport object
        public void setHealth(int health) {
            int oldValue = this.health;
            int newValue = health;
            this.health = health;
    
            // notify observers of change in the HEALTH property
            pcSupport.firePropertyChange(HEALTH, oldValue, newValue);
        }
    
        public String getName() {
            return name;
        }
    
        // allow listeners/observers to be added
        public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
            pcSupport.addPropertyChangeListener(name, listener);
        }
    
        // ....... other methods
    
    }
    

    请注意,玩家类不需要知道它显示在什么GUI中,观察者将如何处理他们观察到的任何信息

    现在我们把这个播放器放在一个简单的GUI中,一个JPanel,它有一个JSlider,允许我们更改播放器健康属性的状态。此类代码的一个片段可能如下所示:

    class PlayerPanel extends JPanel {
        private Player player;
        private JSlider healthSlider = new JSlider(Player.HEALTH_MIN, Player.HEALTH_MAX, 0); 
    
        public PlayerPanel(Player player) {
            this.player = player;
    
            healthSlider.setValue(player.getHealth());
            healthSlider.setMajorTickSpacing(20);
            healthSlider.setMinorTickSpacing(5);
            healthSlider.setPaintTicks(true);
            healthSlider.setPaintLabels(true);
    
            // call method to change the player's health when the slider changes
            healthSlider.addChangeListener(clEvent -> healthChange());
    
            JPanel namePanel = new JPanel();
            namePanel.add(new JLabel("Player Name:"));
            namePanel.add(Box.createHorizontalStrut(5));
            namePanel.add(new JLabel(player.getName()));
    
            setLayout(new BorderLayout());
            add(namePanel, BorderLayout.PAGE_START);
            add(healthSlider);
        }
    
        // ........ other methods
    
    
        private void healthChange() {
            player.setHealth(healthSlider.getValue());
        }
    
        // .......... other methods
    }
    

    然后在另一个类中,一个有JProgressBars的类中,我们可以在progressBar中显示玩家的健康状况,并让侦听器在健康状况发生变化时更新progressBar:

    // create a Player object
    Player player = new Player(playerName);
    
    // create a JProgressBar to show the health
    final JProgressBar progressBar = new JProgressBar(Player.HEALTH_MIN, Player.HEALTH_MAX);
    progressBar.setStringPainted(true);
    progressBar.setValue(player.getHealth()); // set initial value
    
    // add a PropertyChangeListener to Player to be notified when HEALTH changes
    player.addPropertyChangeListener(Player.HEALTH, pcEvent -> setProgress(progressBar, player));            
    

    我们将通过setProgress方法更新JProgressBar:

    private void setProgress(JProgressBar progressBar, Player player) {
        int health = player.getHealth();
        progressBar.setValue(health);
    }
    

    整个工作示例可能是这样的:

    import java.awt.BorderLayout;
    import java.awt.Dialog.ModalityType;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.Window;
    import java.beans.PropertyChangeListener;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    import javax.swing.event.SwingPropertyChangeSupport;
    
    @SuppressWarnings("serial")
    public class JProgressHealth extends JPanel {
        public static final String[] PLAYER_NAMES = {"John", "Steve", "Frank", "Judy", "Hillary", "Billy"};
        private List<Player> players = new ArrayList<>();
    
        public JProgressHealth(Window owner) {
            setLayout(new GridLayout(0, 1));
            for (String playerName : PLAYER_NAMES) {
                Player player = new Player(playerName);
                final JProgressBar progressBar = new JProgressBar(Player.HEALTH_MIN, Player.HEALTH_MAX);
                progressBar.setStringPainted(true);
                progressBar.setValue(player.getHealth());
                player.addPropertyChangeListener(Player.HEALTH, pcEvent -> setProgress(progressBar, player));            
                JPanel titlePanel = new JPanel(new BorderLayout());
                titlePanel.add(progressBar);
                titlePanel.setBorder(BorderFactory.createTitledBorder(player.getName()));
                add(titlePanel);
    
                // create player panels to illustrate how this works
                PlayerPanel playerPanel = new PlayerPanel(player);
                JDialog dialog = new JDialog(owner, player.getName(), ModalityType.MODELESS);
                dialog.add(playerPanel);
                dialog.pack();
                dialog.setLocationByPlatform(true);
                dialog.setVisible(true);
            }
        }
    
        // make JPanel wider
        @Override
        public Dimension getPreferredSize() {
            Dimension superSize = super.getPreferredSize();
            int w = 3 * superSize.width;
            int h = superSize.height;
            return new Dimension(w, h);
        }
    
        private void setProgress(JProgressBar progressBar, Player player) {
            int health = player.getHealth();
            progressBar.setValue(health);
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("Health");
    
            JProgressHealth mainPanel = new JProgressHealth(frame);
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    @SuppressWarnings("serial")
    class PlayerPanel extends JPanel {
        private Player player;
        private JSlider healthSlider = new JSlider(Player.HEALTH_MIN, Player.HEALTH_MAX, 0); 
    
        public PlayerPanel(Player player) {
            this.player = player;
    
            healthSlider.setValue(player.getHealth());
            healthSlider.setMajorTickSpacing(20);
            healthSlider.setMinorTickSpacing(5);
            healthSlider.setPaintTicks(true);
            healthSlider.setPaintLabels(true);
            healthSlider.addChangeListener(clEvent -> healthChange());
    
            JPanel namePanel = new JPanel();
            namePanel.add(new JLabel("Player Name:"));
            namePanel.add(Box.createHorizontalStrut(5));
            namePanel.add(new JLabel(player.getName()));
    
            setLayout(new BorderLayout());
            add(namePanel, BorderLayout.PAGE_START);
            add(healthSlider);
        }
    
        // make JPanel wider
        @Override
        public Dimension getPreferredSize() {
            Dimension superSize = super.getPreferredSize();
            int w = 2 * superSize.width;
            int h = superSize.height;
            return new Dimension(w, h);
        }
    
    
        private void healthChange() {
            player.setHealth(healthSlider.getValue());
        }
    
        public Player getPlayer() {
            return player;
        }
    }
    

    class Player {
        public static final int HEALTH_MIN = 0;
        public static final int HEALTH_MAX = 100;
        public static final String HEALTH = "health";
        private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
        private String name;
        int health = 50; // value from 1 to 100
    
        public Player(String name) {
            this.name = name;
        }
    
        public int getHealth() {
            return health;
        }
    
        public void setHealth(int health) {
            int oldValue = this.health;
            int newValue = health;
            this.health = health;
    
            // notify observers of change
            pcSupport.firePropertyChange(HEALTH, oldValue, newValue);
        }
    
        public String getName() {
            return name;
        }
    
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            pcSupport.addPropertyChangeListener(listener);
        }
    
        public void removePropertyChangeListener(PropertyChangeListener listener) {
            pcSupport.removePropertyChangeListener(listener);
        }
    
        public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
            pcSupport.addPropertyChangeListener(name, listener);
        }
    
        public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
            pcSupport.removePropertyChangeListener(name, listener);
        }
    }