I have been learning javafx and I was trying combobox but cant seem to get output out of combobox properly. When I try to use the value from combobox as String it gives me ClassCastException: java.lang.Integer cannot be cast to java.lang.String, and when I try to use the value as an int or an Integer(tried both) it gives me the opposite ClassCastException: java.lang.String cannot be cast to java.lang.Integer.
I have tried getting the value using
comboBox.getSelectionModel().getSelectedItem();
and also with
comboBox.getValue();
I have tried converting the values explicitly with valueOf, parseInt, and toString. Using getClass also gives a ClassCastException: java.lang.String cannot be cast to java.lang.Integer..
This is the combobox I have been using:
<ComboBox fx:id="comboBox" editable="true" promptText="Enter Period in Days" >
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:id="week" fx:value="7" />
<String fx:id="fortnite" fx:value="14" />
<String fx:id="month" fx:value="30" />
<String fx:id="monthx3" fx:value="90" />
<String fx:id="year_2" fx:value="180" />
<String fx:id="year" fx:value="365"/>
</FXCollections>
</items>
</ComboBox>
How do I get a value out of this combobox? What am I doing wrong?
If you're using some type different to String
and want to keep the ComboBox
editable, you need to assign a StringConverter
to the ComboBox.converter
property that is able to convert the String
to the item type of the ComboBox
. Otherwise you'll get the ClassCastException
when the ComboBox
tries to parse the input of the combobox TextField
.
Note: Adding an fx:id
attribute to a element in the fxml does not result in a combination of the fx:id
and the object created for the element to be used. Instead all it does is allow you to inject the instance to a field in the controller or reference the instance later in the fxml.
Since it seems like you want to keep 2 pieces of information (String
and int
) neither String
nor Integer
may work for you. You could create a custom type:
public class NamedDuration {
private final int days;
private final String name;
public NamedDuration(@NamedArg("days") int days, @NamedArg("name") String name) {
this.days = days;
this.name = name;
}
public int getDays() {
return days;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
<ComboBox fx:id="comboBox" editable="true" onAction="#comboChange" promptText="Enter Period in Days">
<items>
<FXCollections fx:factory="observableArrayList">
<NamedDuration name="week" days="7"/>
<NamedDuration name="fortnite" days="14"/>
<NamedDuration name="month" days="30"/>
<NamedDuration name="monthx3" days="90"/>
<NamedDuration name="year_2" days="180"/>
<NamedDuration name="year" days="365"/>
</FXCollections>
</items>
</ComboBox>
public class FXML2Controller {
@FXML
private ComboBox<NamedDuration> comboBox;
@FXML
private void comboChange() {
NamedDuration duration = comboBox.getValue();
if (duration != null) {
System.out.format("%d days = %s\n", duration.getDays(), duration.getName());
}
}
@FXML
private void initialize() {
// set converter to convert between String and NamedDuration
comboBox.setConverter(new StringConverter<NamedDuration>() {
@Override
public String toString(NamedDuration object) {
return object == null ? "" : object.getName();
}
@Override
public NamedDuration fromString(String string) {
if (string == null || string.isEmpty()) {
return null;
}
// try matching names
for (NamedDuration nd : comboBox.getItems()) {
if (nd.getName().equalsIgnoreCase(string)) {
return nd;
}
}
// try matching number
int days;
try {
days = Integer.parseInt(string);
} catch (NumberFormatException ex) {
return null;
}
for (NamedDuration nd : comboBox.getItems()) {
if (days == nd.getDays()) {
return nd;
}
}
return null;
}
});
}
}