如何使对象的实例可供多个swing窗体访问?JAVA

如何使对象的实例可供多个swing窗体访问?JAVA,java,Java,我正在制作一个基于文本的RPG来帮助我学习Java。所以我现在有一堆不同的类来制作swing表单,每一个都会相互联系。然而,在一种形式中,我实际上创建了名为Player的对象的实例,我将根据用户的选择设置统计数据(强度、敏捷性、级别等) 但是,我只能在该类/窗口中访问该对象,并且不能在应用程序中的任何其他位置调用它来操作该对象 如何使其全球可访问 编辑 我应该用更恰当的措辞。假设我有一个名为PlayerCreation的类,在PlayerCreation中,我通过调用Player类Player

我正在制作一个基于文本的RPG来帮助我学习Java。所以我现在有一堆不同的类来制作swing表单,每一个都会相互联系。然而,在一种形式中,我实际上创建了名为Player的对象的实例,我将根据用户的选择设置统计数据(强度、敏捷性、级别等)

但是,我只能在该类/窗口中访问该对象,并且不能在应用程序中的任何其他位置调用它来操作该对象

如何使其全球可访问

编辑

我应该用更恰当的措辞。假设我有一个名为PlayerCreation的类,在PlayerCreation中,我通过调用Player类Player p1=new Player()来创建一个对象;现在我完全离开了这个类,转到另一个叫做PlayerStats的表单,我想调用p1.getStrength();但是由于p1是在PlayerCreation类中,我无法获得它。

我现在正在学习一个Java类,我认为我书中的这个示例将对您有所帮助。在本例中,他们采用了一个可公开访问的“rooms”类

使用单例模式。 如果你给你的班级一个字段,比如:

private static final int agility
或者任何你喜欢的变量,以及像这样的getter:

public static int getAgility() {
    return agility;
}
new ClassNameYouChoose();
您可以在启动时按如下方式实例化该类:

public static int getAgility() {
    return agility;
}
new ClassNameYouChoose();
您可以从任何地方访问getter:

int agility = ClassNameYouChoose();

注意,你不应该“滥用”这个;如果您决定在以后的游戏开发中更改某些内容,那么找出您在何处使用该类内容可能会非常具有挑战性。

以下是我所说的示例。我稍后会添加一些文本,但如果您编译并运行此代码,您将看到它是如何工作的:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class DependInjectEg {
   private static void createAndShowGui() {
      Player[] players = {
            new Player("John Smith", 10, 5),
            new Player("Donald Duck", 8, 3),
            new Player("Doris Day", 5, 2),
            new Player("Bill Jones", 4, 6),
            new Player("Frank Stein", 1, 1),
      };

      PlayerStats mainPanel = new PlayerStats();
      for (Player player : players) {
         mainPanel.addPlayer(player);
      }

      JFrame frame = new JFrame("Dependency Injection Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class Player {
   private String name;
   private int speed;
   private int strength;

   // default constructor
   public Player() {
   }

   public Player(String name, int speed, int strength) {
      this.name = name;
      this.speed = speed;
      this.strength = strength;
   }

   public int getStrength() {
      return strength;
   }

   public void setStrength(int strength) {
      this.strength = strength;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getSpeed() {
      return speed;
   }

   public void setSpeed(int speed) {
      this.speed = speed;
   }

   @Override
   public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append("Name: " + name + ", ");
      sb.append("Speed: " + speed + ", ");
      sb.append("Strength: " + strength);

      return sb.toString();
   }

}

@SuppressWarnings("serial")
class PlayerStats extends JPanel {
   private DefaultListModel playerListModel = new DefaultListModel();
   private JList playerList = new JList(playerListModel);

   public PlayerStats() {
      JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      btnPanel.add(new JButton(new NewPlayerAction()));
      btnPanel.add(new JButton(new EditPlayerAction()));
      btnPanel.add(new JButton(new ExitAction()));

      setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
      setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createTitledBorder("Player Stats"),
            BorderFactory.createEmptyBorder(5, 5, 5, 5)));
      add(new JScrollPane(playerList));
      add(Box.createVerticalStrut(5));
      add(btnPanel);

   }

   public void addPlayer(Player player) {
      playerListModel.addElement(player);
   }

   private class NewPlayerAction extends AbstractAction {
      public NewPlayerAction() {
         super("New Player");
         putValue(MNEMONIC_KEY, KeyEvent.VK_N);
      }

      public void actionPerformed(ActionEvent evt) {
         PlayerEditorPanel editorPanel = new PlayerEditorPanel();
         int result = JOptionPane.showConfirmDialog(PlayerStats.this,
               editorPanel, "Create Player", JOptionPane.OK_CANCEL_OPTION,
               JOptionPane.PLAIN_MESSAGE);
         if (result == JOptionPane.OK_OPTION) {
            Player player = editorPanel.getNewPlayer();
            playerListModel.addElement(player);
         }
      };
   }

   private class EditPlayerAction extends AbstractAction {
      public EditPlayerAction() {
         super("Edit Player");
         putValue(MNEMONIC_KEY, KeyEvent.VK_E);
      }

      public void actionPerformed(ActionEvent evt) {
         Player player = (Player) playerList.getSelectedValue();
         if (player == null) {
            return; // do nothing if no player selected
         }
         PlayerEditorPanel editorPanel = new PlayerEditorPanel();
         editorPanel.setPlayer(player);

         int result = JOptionPane.showConfirmDialog(PlayerStats.this,
               editorPanel, "Edit Player", JOptionPane.OK_CANCEL_OPTION,
               JOptionPane.PLAIN_MESSAGE);
         if (result == JOptionPane.OK_OPTION) {
            editorPanel.upDatePlayerAttributes();
            playerList.repaint();
         }
      }
   }

   private class ExitAction extends AbstractAction {
      public ExitAction() {
         super("Exit");
         putValue(MNEMONIC_KEY, KeyEvent.VK_X);
      }

      public void actionPerformed(ActionEvent e) {
         Window win = SwingUtilities.getWindowAncestor(PlayerStats.this);
         win.dispose();
      }

   }
}

@SuppressWarnings("serial")
class PlayerEditorPanel extends JPanel {
   public static final String[] FIELD_TITLES = { "Name", "Speed", "Strength" };
   private static final Insets WEST_INSETS = new Insets(5, 0, 5, 5);
   private static final Insets EAST_INSETS = new Insets(5, 5, 5, 0);
   private JTextField nameField = new JTextField(10);
   private JTextField speedField = new JTextField(10);
   private JTextField strengthField = new JTextField(10);
   private JTextField[] fields = { nameField, speedField, strengthField };
   private Player player;

   public PlayerEditorPanel() {
      setLayout(new GridBagLayout());
      setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createTitledBorder("Player Editor"),
            BorderFactory.createEmptyBorder(5, 5, 5, 5)));
      GridBagConstraints gbc;
      for (int i = 0; i < FIELD_TITLES.length; i++) {
         gbc = createGbc(0, i);
         add(new JLabel(FIELD_TITLES[i] + ":", JLabel.LEFT), gbc);
         gbc = createGbc(1, i);
         add(fields[i], gbc);
      }
   }

   @SuppressWarnings("static-access")
   private GridBagConstraints createGbc(int x, int y) {
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = x;
      gbc.gridy = y;
      gbc.gridwidth = 1;
      gbc.gridheight = 1;

      // bad coding habit using variable name to access static constants
      // done for sake of brevity and clarity
      gbc.anchor = (x == 0) ? gbc.WEST : gbc.EAST;
      gbc.fill = (x == 0) ? gbc.BOTH : gbc.HORIZONTAL;

      gbc.insets = (x == 0) ? WEST_INSETS : EAST_INSETS;
      gbc.weightx = (x == 0) ? 0.1 : 1.0;
      gbc.weighty = 1.0;
      return gbc;
   }

   public void setPlayer(Player player) {
      this.player = player;
      nameField.setText(player.getName());
      speedField.setText(String.valueOf(player.getSpeed()));
      strengthField.setText(String.valueOf(player.getStrength()));
   }

   public Player getNewPlayer() {
      String name = nameField.getText();
      int strength = 0;
      try {
         strength = Integer.parseInt(strengthField.getText());
      } catch (NumberFormatException e) {
         // TODO: notify user that field was empty
      }
      int speed = 0;
      try {
         speed = Integer.parseInt(speedField.getText());
      } catch (NumberFormatException e) {
         // TODO: notify user that field was empty
      }

      Player p = new Player();
      p.setName(name);
      p.setSpeed(speed);
      p.setStrength(strength);

      return p;
   }

   public void upDatePlayerAttributes() {
      String name = nameField.getText();
      int strength = 0;
      try {
         strength = Integer.parseInt(strengthField.getText());
      } catch (NumberFormatException e) {
         // TODO: notify user that field was empty
      }
      int speed = 0;
      try {
         speed = Integer.parseInt(speedField.getText());
      } catch (NumberFormatException e) {
         // TODO: notify user that field was empty
      }

      player.setName(name);
      player.setSpeed(speed);
      player.setStrength(strength);
   }
}
这将在JTextField中显示播放器的属性,并将设置一个内部私有变量Player来引用这个注入的播放器对象。这在PlayerStats类中调用,如下所示:

  public void actionPerformed(ActionEvent evt) {

     // *** first get the selected Player from the JList
     Player player = (Player) playerList.getSelectedValue();
     if (player == null) {
        return; // do nothing if no player selected
     }

     // then create a PlayerEditorPanel object
     PlayerEditorPanel editorPanel = new PlayerEditorPanel();

     // and then "inject" the selected Player into the editor panel.
     editorPanel.setPlayer(player);

     // and display it in a JOptionPane
     int result = JOptionPane.showConfirmDialog(PlayerStats.this,
           editorPanel, "Edit Player", JOptionPane.OK_CANCEL_OPTION,
           JOptionPane.PLAIN_MESSAGE);
     if (result == JOptionPane.OK_OPTION) {
        editorPanel.upDatePlayerAttributes();
        playerList.repaint();
     }
  }
然后,如果您决定接受更改后的属性,则可以调用
upDatePlayerAttributes()
方法,将这些属性赋予Player变量所持有的Player对象:

public void upDatePlayerAttributes() {
  String name = nameField.getText();
  int strength = 0;
  try {
     strength = Integer.parseInt(strengthField.getText());
  } catch (NumberFormatException e) {
     // TODO: notify user that field was empty
  }
  int speed = 0;
  try {
     speed = Integer.parseInt(speedField.getText());
  } catch (NumberFormatException e) {
     // TODO: notify user that field was empty
  }

  player.setName(name);
  player.setSpeed(speed);
  player.setStrength(strength);
}

有意义吗?

可能重复-注意各种答案;依赖项注入通常是一种很好的方法。@Ben Allen:您将类公开了吗?@Brian的建议是:使用依赖项注入传递引用,就像对非GUI Java类传递引用一样。并继续遵循良好的面向对象指导原则,避免使用静态变量之类的东西。我应该更好地表达这一点。假设我有一个名为PlayerCreation的类,在PlayerCreation中,我通过调用Player类Player p1=new Player()来创建一个对象;现在我完全离开了这个类,转到另一个叫做PlayerStats的表单,我想调用p1.getStrength();但由于p1在PlayerCreation类中,我无法理解它。@HovercraftFullOfEels您对依赖注入有更好的解释吗?我很困惑:(他希望能够对修改类和游戏类中可访问的玩家对象进行更改。单例模式绝对不是解决这个问题的方法。同样,解决方案是通过依赖项注入。-1非常好,是的,这很有意义!非常感谢!