2017-09-19 11 views
0

맞습니다. 사용자가 우주 마린 (Warhammer 40k) 군대를 만들 수있는 프로그램을 만들려고합니다. 내가 고군분투하는 프로그램. 이 부분을 사용하면 ComboBox에서 'Unit Type'을 선택하고 그 아래의 다른 ComboBox에는 첫 번째 ComboBox에서 선택한 'Unit Type'에 대한 모든 단위가 채워집니다.JavaFX - ComboBox에서 ChangeListener를 사용하여 두 번째 ComboBox를 여러 ArrayLists로 채우기

예를 들어 첫 번째 ComboBox에서 엘리트 '유닛 유형'을 선택한 경우 두 번째 ComboBox에 엘리트 '유닛 유형'의 모든 유닛이 채워 져야합니다 : "Dreadnought", "Ironclad Dreadnought" , "공격 대장", "백부장 공격", "명령", "명예 경비대", "스턴 가드 베테랑", "터미네이터", "뱅가드 참전 용사"등이 있습니다. 각각 8 개의 '유닛 유형'이 있습니다.

이 설정은 다음과 같습니다. unitTypeList라는 'Unit Types'목록이 있습니다. 이 목록에는 8 개의 '단위 유형'이 모두 있습니다. 나는 또한 'Unit Type'에 대해 여러 개의 단위를 보유하고있는 8 개의 별도의 목록 (각각 'Unit Type'을 나타냄)을 가지고 있습니다. 그런 다음 앞서 언급 한 8 개의 개별 목록을 보유하는 목록이 하나 더 있습니다. 그래서 그것은 목록입니다. thats에는 8 개의 다른 목록이 있습니다.

첫 번째 ComboBox를 'Unit Types'로 채우기 위해 unitTypeList를 unitTypeOlist라는 ObservableList에 배치했습니다. 그런 다음 첫 번째 ComboBox에 ObservableList unitTypeOList를 채 웁니다. 이것은 잘 작동합니다.

이제 올바른 단위로 두 번째 ComboBox를 채우려면 첫 번째 ComboBox에 ChangeListener를 추가하기로 결정했습니다. 따라서 첫 번째 ComboBox의 입력을 받아 두 번째 ComboBox를 기준으로 단위를 올바르게 채울 수 있습니다. 첫 번째 ComboBox에서 'Unit Type'을 선택합니다.

그러나 여기에서 문제가 발생합니다. ChangeListener에 또 다른 ObservableList를 만들고 'Unit Type'의 각 단위를 포함하는 8 개의 개별 목록을 보유하는 List를 배치합니다. 그러나 프로그램을 실행하고 첫 번째 ComboBox에서 'Unit Type'을 선택하려고하면 프로그램이 거대한 오류로 종료됩니다. "JavaFX Application Thread"스레드의 예외 java.lang.ClassCastException : gui.model.Unit_Type을 java.lang.Integer로 형변환 할 수 없습니다.

int 로의 캐스팅과는 분명히 관련이 있습니다. 그러나 나는 ChangeListener를 다른 방법으로 사용하여 원하는 것을 어떻게 얻을 수 있을지 확신하지 못합니다. 첫 번째 단락의 요구 사항을 충족하려면 도움이 필요합니다.

이미 검색을 시도했으며 이미 this question 매우 도움이됨을 발견했습니다. (내 설정은이 질문을 기반으로합니다.)하지만 내 요구 사항은 다소 복잡하다고 생각합니다. 여기

내 프로그램의 AddUnitPane 클래스의 코드는 (내가 그것을 내가 할 수있는 최선을 언급하려고했습니다)입니다 :

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);  
    } 
} 

답변

1

이 말은 원시 타입을 사용하지 말아야하는 이유 중 하나입니다 .

ChangeListenerProperty<Unit_Type> 대신 IntegerProperty을 청취하는 것처럼 작성됩니다. ChangeListener<Integer> 대신 사용 된 경우

unitList.get((int) arg2) 

귀하의 컴파일러는이 문제에 대해 불평 것 : 캐스트는이 표현에서 예외를 얻을 수 있도록 IntegerUnit_Type 개체 수 없습니다 형성한다.

대신 selectedIndex 속성을 청취 할 수 있습니다 (물론 유효한 인덱스 - -1도 가능한 값입니다).

단순히 목록을 속성으로 Unit_Type에 추가하는 것이 더 쉽습니다. BTW

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()); 
    } 
}); 

: 당신이 목록의 크기를 조정하지 때문에, 그것들을 초기화하는 다음과 같은 방법이 훨씬 간단 할 것이다 : 심지어

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

당신이 경우에 당신이 이런 식으로 뭔가를 작성할 수 있습니다 것 특정 목록 유형을 사용하려면 상용구 코드를 줄이고 도우미 메서드를 도입하는 것이 좋습니다.

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

Unit_Type 클래스에서 getUnits 메소드가 필요합니까? 나는 그 부분에서 조금 혼란 스럽다. 나는 getUnits 메소드를 위해 무엇을 반환해야하는지 정확히 모르겠습니다. 해야 할 목록을 반환해야합니다 다른 8 개의 하위 목록을 보유하고 색인을 선택합니까? 내 Unit_Type 클래스는 단위의 집합임을 유의해야합니다. 유닛이 ArrayList 인 경우 필요한 경우 Unit_Type 클래스를 공유 할 수 있습니다. – GR412

+0

'getUnits'는 주어진 타입의 단위를 포함하는 ObservableList 을 반환 할 것입니다 ... – fabian

+0

단위의 목록을 추가하려고하면 작동하지 않는 것처럼 보입니다. . 각 단위 유형에 seprate 문자열을 추가 할 때만 작동합니다. 나는 내가 의미하는 바를 더 잘 이해하는 또 다른 질문을 올렸다. 어쩌면 당신이 볼 수 있을지도 모른다 : https://stackoverflow.com/questions/46342627/javafx-using-a-changelistener-on-a-combobox-to-populate-another-combobox-with – GR412