两天前,我发布了this question,内容是将ChangeListener附加到ComboBox,以规定在第二个ComboBox上显示什么输出。简而言之,第一个ComboBox显示了一些单元类型,而取决于所选的单元类型将取决于基于所选的单元类型在第二个ComboBox中显示的单元列表。例如,如果您在第一个ComboBox中选择了“精英”单元类型,那么第二个ComboBox应该填充所有“精英”单元。
现在,回答my original question的人在ChangeListener中的代码方面帮了很多忙,我确实设法让它正常工作。但是,目前只有当您一次向unit添加一个单元时,它才能工作。理想情况下,我希望向Unit中添加一个ArrayList或其他合适的单元数据结构,而不是单个单元。这将减少代码,并更有效。
因此,正如您在这个代码片段中所看到的,当前精英单元类型addUnit方法一次只接受单个字符串,
elites = new Unit_Type("Elites");
elites.addUnit("Dreadnought");
elites.addUnit("Ironclad Dreadnought");根据我的意愿,我可以在精英单元类型的ArrayList方法中添加一个addUnit或模拟数据结构,比如这个代码片段:
elitesList = createArrayList("Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard","Sternguard Veteran", "Terminator", "Vanguard Veterans");
elites = new Unit_Type("Elites");
elites.addUnit(elitesList);注意,elitesList是由helper方法生成的,因为还有8个类似的列表,每个列表都代表不同的Unit。现在,我尝试更改Unit类中的代码,使单元ArrayList类型为ArrayList<String>,并尝试更改addUnit方法以接受ArrayList<String>的参数,但每当我运行程序时,在第一个ComboBox中选择Unit将导致第二个ComboBox中出现一个空数组。
下面是AddUnitPane类(视图)和Unit_Type类(模型)的其余代码
AddUnitPane类
public class AddUnitPane extends GridPane
{
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;
private ArrayList<String> elitesList, fastAtkList, heavySptList, hqList, lordsowList, specialCList, transportList, troopsList; //Declare the sublists that hold all the units for the type of unit
Unit_Type elites, fastAttk, heavySpt, hQ, lordsOW, specialC, transport, troops;
public AddUnitPane()
{
this.setVgap(15);
this.setHgap(20);
this.setAlignment(Pos.CENTER);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHalignment(HPos.RIGHT);
this.getColumnConstraints().add(col1);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
elitesList = createArrayList("Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard",
"Sternguard Veteran", "Terminator", "Vanguard Veterans");
fastAtkList = createArrayList("Attack Bike", "Stormhawk Interceptor", "Stormtalon Gunship", "Assault", "Bike", "Land Speeder", "Scout Bike");
heavySptList = createArrayList("Hunter", "Land Raider Crusader", "Land Raider Redeemer", "Land Raider", "Predator", "Stalker", "Stormraaven Gunship", "Vindicator",
"Whirlwind", "Centurion Devastator", "Devastator", "Thunderfire Cannon");
hqList = createArrayList("Captain", "Chaplain", "Librarian", "Techmarine");
lordsowList = createArrayList("Marneus Calger", "Roboute Guilliman");
specialCList = createArrayList("Antaro Chronus", "Cato Sicarius", "Ortan Cassius", "Torias Telion", "Varro Tigurius");
transportList = createArrayList("Drop Pod", "Land Speeder Storm", "Razorback", "Rhino");
troopsList = createArrayList("Scout", "Tactical");
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
elites = new Unit_Type("Elites");
//elites.addUnit(elitesList);
elites.addUnit("Dreadnought");
elites.addUnit("Ironclad Dreadnought");
fastAttk = new Unit_Type("Fast Attack");
fastAttk.addUnit("Attack Bike");
fastAttk.addUnit("Stormhawk Interceptor");
ObservableList<Unit_Type> unitTypeOList = FXCollections.observableArrayList(elites, fastAttk); //add each Unit_Type to an Observable List
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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 (first ComboBox)
unitTypeCombo.setItems(unitTypeOList); //Populate the unitTypeCombo with the UnitTypeOList (observable list) from line 82
//unitTypeCombo.getSelectionModel().selectFirst(); //Set the unitTypeCombo to show the first item
unitCombo = new ComboBox<>(); //Initialise the unitCombo (second ComboBox)
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.getUnitsForType());
}
});
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 void AddUnitHandler(EventHandler<ActionEvent> handler)
{
addSquadBtn.setOnAction(handler);
}
private static <T> ArrayList<T> createArrayList(T... items) //generates the unit lists
{
ArrayList<T> result = new ArrayList<>(items.length);
for (T item : items)
{
result.addAll(result);
}
return result;
}
}Unit_Type类
public class Unit_Type implements Serializable
{
private String typeName;
private ArrayList<String> units; //a unit type is an aggregation of units. Tried changing this type to ArrayList<String>
public Unit_Type(String typeName)
{
this.typeName = typeName;
units = new ArrayList<>();
}
public void addUnit(String u) //tried changing this parameter to ArrayList<String>
{
units.add(u);
}
public void setTypeName(String name)
{
typeName = name;
}
public ObservableList<String> getUnitsForType() //method used in the ChangeListener in the AddUnitPane class
{
ObservableList unitsOList = FXCollections.observableArrayList(units);
return unitsOList;
}
@Override
public String toString() //allows the ComboBox to display values correctly
{
return typeName;
}
}发布于 2017-09-21 15:21:55
我不会将支持列表存储在Unit_Type类中。最好将ObservableList存储在字段中,编写自定义序列化方法,并使字段暂时化。
通过这种方式,您还可以使用
elites.getUnitsForType().addAll("Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought", "Assault Terminator", "Centurion Assault", "Command", "Honour Guard",
"Sternguard Veteran", "Terminator", "Vanguard Veterans");但是,在构造函数中初始化列表可能更短:
public class Unit_Type implements Serializable {
private String typeName;
private transient ObservableList<String> units;
private void writeObject(ObjectOutputStream stream)
throws IOException {
stream.defaultWriteObject();
// serialize units list as string array
stream.writeObject(units.toArray());
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
// read array from stream and initialize list with it
// Note: because of the way we write objects of this type we can use the raw type here safely
units = (ObservableList) FXCollections.<Object>observableArrayList((Object[])stream.readObject());
}
public Unit_Type(String typeName, String... units) {
this.typeName = typeName;
this.units = FXCollections.observableArrayList(units);
}
public void setTypeName(String name) {
typeName = name;
}
public ObservableList<String> getUnitsForType() {
return units;
}
@Override
public String toString() {
return typeName;
}
}elites = new Unit_Type("Elites",
"Dreadnought", "Ironclad Dreadnought", "Venerable Dreadnought",
"Assault Terminator", "Centurion Assault", "Command",
"Honour Guard", "Sternguard Veteran", "Terminator",
"Vanguard Veterans"
);在(反序列化)过程中,除ObservableList之外的一切都是使用默认序列化机制处理的。
stream.defaultWriteObject();stream.defaultReadObject();transient关键字会导致忽略该字段(通常情况下,ObservableList是不可序列化的,因为很难/不可能持久化监听器,特别是如果它们引用UI元素的话)。在本例中,我们只需将列表中的字符串读写为数组:
stream.writeObject(units.toArray());units = (ObservableList) FXCollections.<Object>observableArrayList((Object[])stream.readObject());有关详细信息,请参阅自定义默认协议部分:http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
https://stackoverflow.com/questions/46342627
复制相似问题