2016-12-22 9 views
0

, поэтому я пытаюсь запрограммировать настольную игру RPG или, по крайней мере, ее часть.Открытие второй рамки очищает все объекты, удерживаемые ArrayLists в первом кадре

У меня есть два кадра, один из которых является основной рамкой, где происходит игра. Второй кадр предназначен для создания персонажа.

Я инициализирую второй кадр кнопкой в ​​первом кадре. Во вновь открывшемся кадре игрок может установить свои значения и создать персонаж.

Проблема, которая ocurring мне, что как только я попал в линию

cw = new CreationWindow(); 

ArrayList playerlist, который содержит символ-объекты, кажется, очищен. Я проверил это в режиме отладки и контрольной точке прямо перед и после этой строки, и показал, что именно здесь ArrayList теряет свои удерживаемые объекты.

Я не совсем понимаю, что там происходит, и я был бы рад, если бы кто-нибудь мог это объяснить мне!

Классы, используемые:

MainWindow

public class MainWindow extends JFrame { 

private CreationWindow cw; 

private JPanel contentPane; 

// Startscreen 
private ArrayList<JButton> startscreenCreateList = new ArrayList<JButton>(); 
private ArrayList<JLabel[]> playerValuelist = new ArrayList<JLabel[]>(); 

// Objects 
private ArrayList<Character> playerlist = new ArrayList<Character>(); 

public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       MainWindow frame = new MainWindow(); 
       frame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

public MainWindow() { 
    setTitle("Legends of Andor"); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 550, 460); 
    setResizable(false); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    contentPane.setLayout(null); 
    setContentPane(contentPane); 

    // Startscreen 
    setStartscreen(); 

} 

private void setStartscreen() { 
    for (int x = 0; x < 4; x++) { 
     startscreenCreateList.add(new JButton("Add")); 
     startscreenCreateList.get(x).setBounds(40, 45 + x * 95, 100, 30); 
     startscreenCreateList.get(x).addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent ae) { 
       /* 
       * 1. the initialization of the CreationWindow Object seems to set every ArrayList of MainWindow "null" 
       * "null" 
       */ 
       cw = new CreationWindow(); 
       cw.setVisible(true); 
      } 
     }); 
     contentPane.add(startscreenCreateList.get(x)); 

     // Start-Button 
     JButton start = new JButton("Start!"); 
     start.setBounds(410, 370, 100, 30); 
     contentPane.add(start); 
    } 

} 

// Methods 
public void createCharacter(Character c) { 
    /* 
    * 5. adds Character Object received from CreationWindow to ArrayList 
    */ 
    playerlist.add(c); 
    System.out.println(playerlist.size()); 
} 
} 

CreationWindow

public class CreationWindow extends JDialog { 

private JPanel contentPane; 

private JLabel[] labels = new JLabel[5]; 
private JTextField name; 
private ArrayList<JComboBox<String[]>> inputFields = new ArrayList<JComboBox<String[]>>(); 
private JButton create; 

private MainWindow hf = new MainWindow(); 
private Character c; 

public CreationWindow() { 
    setTitle("Create a Character!"); 
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    setBounds(100, 100, 300, 250); 
    setResizable(false); 
    setModal(true); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    contentPane.setLayout(null); 
    setContentPane(contentPane); 

    setCreationScreen(); 

    // Create Character 
    create.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent ae) { 

      /* 
      * 2. As the class Character is abstract, the Object needs to be initialized with a subclass 
      */ 

      switch (inputFields.get(0).getSelectedIndex()) { 
      case 0: 
       c = new Bowman(); 
       break; 
      case 1: 
       c = new Warrior(); 
       break; 
      case 2: 
       c = new Sorcerer(); 
       break; 
      case 3: 
       c = new Dwarf(); 
       break; 
      } 

      /* 
      * 3. setting values of the Character Object 
      */ 

      c.setCharacter(name.getText(), inputFields.get(1).getSelectedIndex() + 1, 
        inputFields.get(2).getSelectedIndex(), inputFields.get(3).getSelectedIndex()); 

      /* 
      * 4. goes back into MainWindow 
      */ 

      hf.createCharacter(c); 
      dispose(); 
     } 
    }); 
} 

private void setCreationScreen() { 
    // Erstellung Arrays für combobox-items 
    String[] points = new String[29]; 
    String[] hours = new String[10]; 
    String[] classes = new String[4]; 

    // Initialisierung Arrays 
    for (int x = 0; x < 29; x++) { 
     if (x < 10) { 
      hours[x] = String.valueOf(x); 
     } 
     points[x] = String.valueOf(x + 1); 
    } 
    classes[0] = "Bowman"; 
    classes[1] = "Warrior"; 
    classes[2] = "Sorcerer"; 
    classes[3] = "Dwarf"; 

    int a = -20; 
    for (int x = 0; x < 5; x++) { 
     labels[x] = new JLabel(); 
     if (x < 4) { 
      if (x < 1) { 
       inputFields.add(new JComboBox(classes)); 
      } else if (x < 2) { 
       inputFields.add(new JComboBox(points)); 
      } else { 
       inputFields.add(new JComboBox(hours)); 
      } 
      if (x < 1) { 
       inputFields.get(x).setBounds(25, a + 120, 110, 20); 
       labels[x].setBounds(25, a + 105, 100, 15); 
      } else { 
       inputFields.get(x).setBounds(160, a + 100 + (x - 2) * 40, 80, 20); 
       labels[x].setBounds(160, a + 85 + (x - 2) * 40, 90, 15); 
      } 
      contentPane.add(inputFields.get(x)); 
     } else { 
      labels[x].setBounds(25, a + 45, 100, 15); 
     } 
     contentPane.add(labels[x]); 
    } 
    labels[0].setText("Character-Class"); 
    labels[1].setText("Willpoints"); 
    labels[2].setText("Strengthpoints"); 
    labels[3].setText("Hours"); 
    labels[4].setText("Name"); 

    name = new JTextField(); 
    name.setBounds(25, a + 60, 110, 20); 
    contentPane.add(name); 

    create = new JButton("Create"); 
    create.setBounds(160, 165, 100, 30); 
    contentPane.add(create); 
} 

}

Характер

public abstract class Character { 

private String name; 
private int willpoints; 
private int strenghtpoints; 
private int hours; 
private boolean isKo = false; 

// Constructor 
public Character() { 

} 

public Character(String n, int wp, int sp, int h) { 
    name = n; 
    willpoints = wp; 
    strenghtpoints = sp; 
    hours = h; 
} 

public void setCharacter(String n, int wp, int sp, int h) { 
    name = n; 
    willpoints = wp; 
    strenghtpoints = sp; 
    hours = h; 
} 

// Getters and Setters 

// Methods 

}

Подклассы наследуются от персонажа и пока не имеют каких-либо различий.

подклассы: Bowman, Гном, Волшебник, Воин

Большое спасибо!

ответ

1

У тебя проблема:

public class CreationWindow extends JDialog { 

    // .... 

    private MainWindow hf = new MainWindow(); 

Вы создаете совершенно новый экземпляр MainWindow уникальный в пределах CreationWindow, и любые изменения, сделанные к этому объекту не будут отражены в первоначальном MainWindow, который отображает графический интерфейс ,

Решение должно передать действительную ссылку на исходный экземпляр MainWindow в ваш новый объект CreationWindow. Для этого используйте конструктор CreationWindow.

i.e.,

public class CreationWindow extends JDialog { 

    // .... 

    private MainWindow hf; // do not instantiate 

    public CreationWindow(MainWindow hf) {  
     this.hf = hf; 

И называют это нравится:

cw = new CreationWindow(MainWindow.this); 

Unrelated вопрос - вы действительно не хотите, чтобы это сделать:

contentPane.setLayout(null); 

Использование пустых макетов и setBounds(...) МАЕ как отличный способ легко создавать сложные графические интерфейсы, но как только вы выйдете за рамки новичка, вы узнаете, что таким образом неправильно, что это только делает вещи намного сложнее для вас и для ваших пользователей. Избегайте этого, за исключением очень определенных исключений (и это не одно), а вместо этого изучите и используйте менеджеров компоновки.

+0

Я люблю тебя. Вызов CreationWindow находится внутри ActionListener, поэтому (это) не будет работать. Можете ли вы мне помочь и там? Как сообщить конструктору, что «это» не является ActionListener, а классом MainWindow? – unnamed

+0

@unnamed использует объект-специфический 'this' здесь:' MainWindow.this'. –

+0

Nevermind, нашел это. Большое спасибо! – unnamed