JavaFx Combobox 值行为怪异

JavaFx Combobox value acting wierd

我一直在学习 javafx,我正在尝试组合框,但似乎无法正确地从组合框中获取输出。当我尝试将组合框的值用作字符串时,它给我 ClassCastException: java.lang.Integer cannot be cast to java.lang.String,当我尝试将该值用作 int 或 Integer(都尝试过)时给我相反的 ClassCastException: java.lang.String cannot be cast to java.lang.Integer.

我尝试使用

获取值
comboBox.getSelectionModel().getSelectedItem();

还有

comboBox.getValue();

我已经尝试使用 valueOf、parseInt 和 toString 显式转换值。使用 getClass 还会产生 ClassCastException:java.lang.String cannot be cast to java.lang.Integer..

这是我一直在使用的组合框:

<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>

如何从此组合框中获取值?我做错了什么?

您的 FXCollections return 字符串,因为您在集合中声明了字符串。如果你想要整数试试这个:

<ComboBox fx:id="comboBox"  editable="true" promptText="Enter Period in Days"  >
    <items>
        <FXCollections fx:factory="observableArrayList">
            <Integer fx:id="week" fx:value="7" />
            <Integer fx:id="fortnite" fx:value="14" />
            <Integer fx:id="month" fx:value="30" />
            <Integer fx:id="monthx3" fx:value="90" />
            <Integer fx:id="year_2" fx:value="180" />
            <Integer fx:id="year" fx:value="365"/>
        </FXCollections>
    </items>
</ComboBox>

并且 comboBox.getValue(); 应该return整数。

如果您使用与 String 不同的类型并希望保持 ComboBox 可编辑,您需要将 StringConverter 分配给 ComboBox.converter 属性 能够将 String 转换为 ComboBox 的项目类型。否则,当 ComboBox 尝试解析组合框 TextField.

的输入时,您将得到 ClassCastException

注意:将 fx:id 属性添加到 fxml 中的元素不会导致 fx:id 和为要使用的元素创建的对象的组合。相反,它所做的只是允许您将实例注入控制器中的字段或稍后在 fxml 中引用实例。

因为您似乎想要保留 2 条信息(Stringint),所以 StringInteger 都不适合您。您可以创建自定义类型:

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>

控制器class

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

        });
    }

}