2017-09-19 14 views
0

Richtig, ich versuche, ein Programm zu erstellen, das es einem Benutzer ermöglicht, eine Space Marines (Warhammer 40k) Armee zu bauen und einen speziellen Teil der Programm, mit dem ich kämpfe. Dieser Teil ermöglicht dem Benutzer die Auswahl eines Einheitentyps aus einer ComboBox. Anschließend wird eine weitere ComboBox darunter mit allen Einheiten für den Einheitentyp gefüllt, den Sie in der ersten ComboBox ausgewählt haben.JavaFX - Verwenden eines ChangeListener auf einer ComboBox zum Auffüllen einer zweiten ComboBox mit mehreren ArrayLists

Wenn Sie zum Beispiel den Einheitentyp der Elite in der ersten ComboBox ausgewählt haben, dann sollte die zweite ComboBox mit allen Einheiten des Elitentyps gefüllt sein, die wie folgt lauten: "Dreadnought", "Ironclad Dreadnought" "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Ehrengarde", "Sternguard Veteran", "Terminator", "Vanguard Veterans". Es gibt 8 'Unit-Typen' mit jeweils eigenen Einheiten.

Die aktuelle Einstellung muss ich erreichen; Ich habe eine Liste von Unit-Typen namens unitTypeList. Diese Liste enthält alle 8 'Einheitentypen'. Ich habe auch 8 andere separate Listen (die jeweils einen 'Einheitentyp' repräsentieren), die mehrere Einheiten für diesen 'Einheitentyp' enthalten. Dann habe ich eine weitere Liste, die jede der 8 separaten Listen enthält, wie zuvor erwähnt. Es ist also eine Liste, die 8 andere Listen enthält.

Um die erste ComboBox mit den Unit-Typen zu füllen, habe ich unitTypeList in eine ObservableList namens unitTypeOlist gestellt. Ich habe dann die erste ComboBox mit dieser ObservableList unitTypeOList gefüllt. Das funktioniert gut.

Jetzt, um die zweite ComboBox mit den richtigen Einheiten zu füllen, entschied ich, einen ChangeListener der ersten ComboBox hinzuzufügen, so kann es die Eingabe der ersten ComboBox nehmen und dann richtig die zweite ComboBox mit den Einheiten basierend auf die Auswahl des 'Unit Type' in der ersten ComboBox.

Aber das ist, wo das Problem auftritt. Ich habe eine weitere ObservableList im ChangeListener erstellt und platziere die Liste, die die 8 separaten Listen enthält, die jede Einheit für den 'Unit Type' enthalten. Wenn ich jedoch versuche, das Programm auszuführen und einen Einheitentyp aus der ersten ComboBox auszuwählen, endet das Programm mit einem gigantischen Fehler, der mit beginnt; Ausnahme im Thread "JavaFX Application Thread" java.lang.ClassCastException: gui.model.Unit_Type kann nicht in java.lang.Integer umgewandelt werden.

Es ist eindeutig etwas mit dem Gießen zu einem Int zu tun. Aber ich bin mir nicht sicher, wie ich mit einem ChangeListener auf andere Weise erreichen würde, was ich will. Ich brauche etwas Hilfe, um die Anforderungen im ersten Absatz zu erfüllen.

Ich habe bereits versucht, dies zu suchen, und fand this question sehr hilfreich bereits. (Mein Setup basiert stark auf dieser Frage) Aber ich denke, dass meine Anforderungen etwas komplexer sind. Hier

ist der Code für die AddUnitPane Klasse meines Programms (Ich habe versucht, es die beste Kommentar, ich kann):

package gui.view; 

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 

import elites.terminator.Terminator; 
import gui.model.Unit; 
import gui.model.Unit_Type; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.HPos; 
import javafx.geometry.Pos; 
import javafx.scene.control.Button; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.ColumnConstraints; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import troops.scout.Scout; 

public class AddUnitPane extends GridPane 
{ 
    private List<Unit_Type> unitTypeList; //Declare the unitTypeList, which holds a list of unit types 
    private List<String> elitesList, fastAtkList, heavySptList, hqList, lordsowList, specialCList, transportList, troopsList; //Declare the sublists that hold all the units for the type of unit 
    private List<List<String>> unitList; //Declare the unitList that holds all the sublists units 
    private Label unitTypeLbl, unitLbl, squadNameLbl, squadSizeLbl; 
    private ComboBox<Unit_Type> unitTypeCombo; 
    private ComboBox<String> unitCombo; 
    private ComboBox<Integer> squadSizeCombo; 
    private TextField squadNameTf; 
    private Button addSquadBtn; 

    public AddUnitPane() 
    { 
     this.setVgap(15); 
     this.setHgap(20); 
     this.setAlignment(Pos.CENTER); 

     ColumnConstraints col1 = new ColumnConstraints(); 
     col1.setHalignment(HPos.RIGHT); 

     this.getColumnConstraints().add(col1); 

     //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

     unitTypeList = new ArrayList<>(); //Initialise the unitTypeList 
     Collections.addAll(unitTypeList, new Unit_Type("Elites"), new Unit_Type("Fast Attack"), new Unit_Type("Heavy Support"), new Unit_Type("HQ"), new Unit_Type("Lords Of War"), 
       new Unit_Type("Special Characters"), new Unit_Type("Transport"), new Unit_Type("Troops")); //Populate the unitTypeList 

     ObservableList unitTypeOList = FXCollections.observableArrayList(unitTypeList); //Add the UnitTypeList to an observableArrayList 

     //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

     elitesList = new ArrayList<>(); //Initialise and populate all the of the sublists that hold each unit for that type 
     Collections.addAll(elitesList, "Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard", 
       "Sternguard Veteran", "Terminator", "Vanguard Veterans"); 

     fastAtkList = new ArrayList<>(); 
     Collections.addAll(fastAtkList, "Attack Bike", "Stormhawk Interceptor", "Stormtalon Gunship", "Assault", "Bike", "Land Speeder", "Scout Bike"); 

     heavySptList = new ArrayList<>(); 
     Collections.addAll(heavySptList, "Hunter", "Land Raider Crusader", "Land Raider Redeemer", "Land Raider", "Predator", "Stalker", "Stormraaven Gunship", "Vindicator", 
       "Whirlwind", "Centurion Devastator", "Devastator", "Thunderfire Cannon"); 

     hqList = new ArrayList<>(); 
     Collections.addAll(hqList, "Captain", "Chaplain", "Librarian", "Techmarine"); 

     lordsowList = new ArrayList<>(); 
     Collections.addAll(lordsowList, "Marneus Calger", "Roboute Guilliman"); 

     specialCList = new ArrayList<>(); 
     Collections.addAll(specialCList, "Antaro Chronus", "Cato Sicarius", "Ortan Cassius", "Torias Telion", "Varro Tigurius"); 

     transportList = new ArrayList<>(); 
     Collections.addAll(transportList, "Drop Pod", "Land Speeder Storm", "Razorback", "Rhino"); 

     troopsList = new ArrayList<>(); 
     Collections.addAll(troopsList, "Scout", "Tactical"); 

     //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

     unitList = new ArrayList<>(); //Initialise and populate the List thats holds other Lists that hold the different units 
     Collections.addAll(unitList, elitesList, fastAtkList, heavySptList, hqList, lordsowList, specialCList, transportList, troopsList); 

     //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 


     unitTypeLbl = new Label("Select The Unit Class: "); //Initialise all of the labels 
     unitLbl = new Label("Select The Unit: "); 
     squadNameLbl = new Label("Squad Name: "); 
     squadSizeLbl = new Label("Squad Size"); 

     //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

     unitTypeCombo = new ComboBox<Unit_Type>(); //Initialise the unitTypeCombo 
     unitTypeCombo.setItems(unitTypeOList); //Populate the unitTypeCombo with the UnitTypeOList (observable list) from line 56 
     unitTypeCombo.getSelectionModel().selectFirst(); //Set the unitTypeCombo to show the first item 

     unitCombo = new ComboBox<>(); //Initialise the unitCombo 

     unitTypeCombo.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() //add a change listener to the unitTypeCombo 
     { 
      @Override 
      public void changed(ObservableValue arg0, Object arg1, Object arg2) 
      { 
       ObservableList unitOList = FXCollections.observableArrayList(unitList.get((int) arg2)); //add the unitList from line 88 to an observable list and cast arg2 to an int 
       unitCombo.setItems(unitOList); //set the unitCombo items with the observable list from above 

      }   
     }); 

     unitCombo = new ComboBox<>(); 

     squadNameTf = new TextField(); 

     squadSizeCombo = new ComboBox<>(); 

     addSquadBtn = new Button("Add Squad"); 

     this.add(unitTypeLbl, 0, 1); 
     this.add(unitTypeCombo, 1, 1); 

     this.add(unitLbl, 0, 2); 
     this.add(unitCombo, 1, 2); 

     this.add(squadNameLbl, 0, 3); 
     this.add(squadNameTf, 1, 3); 

     this.add(squadSizeLbl, 0, 4); 
     this.add(squadSizeCombo, 1, 4); 

     this.add(new HBox(), 0, 5); 
     this.add(addSquadBtn, 1, 5);   
    } 

    public ComboBox<Unit_Type> getUnitClass() 
    { 
     return unitTypeCombo;  
    } 

    public ComboBox<String> getUnit() 
    { 
     return unitCombo; 
    } 

    public String getSquadName() 
    { 
     return squadNameTf.getText(); 
    } 

    public ComboBox<Integer> getSquadSize() 
    { 
     return squadSizeCombo; 
    } 

    public void AddUnitHandler(EventHandler<ActionEvent> handler) 
    { 
     addSquadBtn.setOnAction(handler);  
    } 
} 

Antwort

1

Dies ist einer der Gründe, warum Sie sollten es vermeiden, die rohe Art mit .

Ihr ChangeListener wird so geschrieben, als ob Sie eine IntegerProperty statt einer Property<Unit_Type> hören würden. Ein Abguss bilden ein Unit_Type Objekt Integer nicht möglich ist, so dass Sie eine Ausnahme in diesem Ausdruck erhalten:

unitList.get((int) arg2) 

Ihr Compiler zu diesem Problem haben sich beschwert, würde, wenn ein ChangeListener<Integer> stattdessen verwendet wurde.

Sie können stattdessen die -Eigenschaft hören (Überprüfung auf gültige Indizes natürlich - -1 ist auch ein möglicher Wert).

Es wäre einfacher, die Liste einfach als Eigenschaft zu Unit_Type hinzuzufügen. Dies würde ermöglichen es Ihnen, so etwas zu schreiben:

unitTypeCombo.valueProperty().addListener(new ChangeListener<Unit_Type>() { 
    @Override 
    public void changed(ObservableValue<? extends Unit_Type> observable, Unit_Type oldValue, Unit_Type newValue) { 
     unitCombo.setItems(newValue == null ? FXCollections.emptyObservableList() : newValue.getUnits()); 
    } 
}); 

BTW: Da Sie nie die Listen Größe ändern, wird die folgende Art und Weise sie zur Initialisierung viel einfacher wäre:

elitesList = Arrays.asList("Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard", 
          "Sternguard Veteran", "Terminator", "Vanguard Veterans"); 
... 

Auch wenn Sie Möchten Sie einen bestimmten Listentyp verwenden, wäre es eine gute Idee, den Standardcode zu reduzieren und eine Hilfsmethode einzuführen:

elitesList = createArrayList("Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard", 
          "Sternguard Veteran", "Terminator", "Vanguard Veterans"); 
... 
+0

Benötige ich eine getUnits-Methode in der Unit_Type-Klasse? Ich bin ein wenig verwirrt in diesem Teil. Ich bin nicht genau sicher, was ich für diese getUnits Methode zurückgeben sollte. Sollte ich meine Liste zurückgeben, die die anderen 8 Unterlisten enthält, dann wähle den Index? Ich sollte beachten, dass meine Unit_Type-Klasse eine Aggregation von Einheiten ist. Eine Unit ist eine ArrayList Ich kann meine Unit_Type-Klasse bei Bedarf teilen. – GR412

+0

'getUnits' würde eine' ObservableList 'zurückgeben, die die Einheiten des angegebenen Typs enthält ... – fabian

+0

Ich denke, ich habe es herausgefunden, aber es scheint nicht zu funktionieren, wenn ich versuche, eine Liste von Einheiten hinzuzufügen . Es funktioniert nur, wenn ich jedem Einheitentyp separate Strings hinzufüge. Ich habe eine weitere Frage gestellt, die eine bessere Vorstellung davon gibt, was ich meine. Wenn es keine Mühe ist, können Sie vielleicht einen Blick darauf werfen: https://stackoverflow.com/questions/46342627/javafx-use-a-changelistener-on-a-combobox-populate-another-combobox-mit – GR412

Verwandte Themen