hashc0der
hashc0der

Reputation: 31

How to set one text in ComboBox items and get different value in javafx fxml

I want to set one combo box value like this

<ComboBox fx:id="dimensionCombo" editable="true" promptText="Other" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="13" GridPane.vgrow="ALWAYS">
            <items>
                <FXCollections fx:factory="observableArrayList">

                  <String fx:value="30X20" />
                  <String fx:value="30X40" />
                  <String fx:value="30X50" />
                  <String fx:value="60X40" />

                </FXCollections>
</ComboBox>

But when I do dimensionCombo.getValue() , I should get a different value like 600 for <String fx:value="30X20" /> , 1200 for <String fx:value="30X40" /> and so on. Is this possible? if yes how?

Now i'm doing (In Controller)

...

if(dimensionCombo.getValue().equals("30X20")) {
    int value = 600;
}
else if(dimensionCombo.getValue().equals("30X40")) {
    int value = 1200;
}

...

Is there any better way of doing this?

Upvotes: 1

Views: 1784

Answers (1)

James_D
James_D

Reputation: 209359

Define a class to hold your data, e.g.:

public class Dimension {

    private final int width ;
    private final int height ;

    public Product(
        @NamedArg("width") int width, 
        @NamedArg("height") int height) {
        this.width = width ;
        this.height = height ;
    }

    public int getWidth() {
        return width ;
    }

    public int getHeight() {
        return height ;
    }

    public int getArea() {
        return width * height ;
    }

    @Override
    public String toString() {
        return String.format("%d X %d", width, height);
    }
}

The @NamedArg annotation allows you to provide constructor arguments in the FXML file, so in your FXML you can do

<ComboBox fx:id="dimensionCombo" editable="true" promptText="Other" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="13" GridPane.vgrow="ALWAYS">
    <items>
        <FXCollections fx:factory="observableArrayList">
              <Dimension width="30" height="20" />
              <Dimension width="30" height="40" />
              <Dimension width="30" height="50" />
              <Dimension width="60" height="40" />

        </FXCollections>
    </items>
</ComboBox>

And in your controller you can do

@FXML
private ComboBox<Dimension> dimensionCombo ;

// ...

int value = dimensionCombo.getValue().getArea();

If you want the combo box to be editable, you need to provide a StringConverter<Dimension>, to allow the combo box to create a new Dimension object from the value typed into the text field. In the controller, add

public void initialize() {
    dimensionCombo.setConverter(new StringConverter<Dimension>() {
        @Override
        public String toString(Dimension d) {
            return d.toString();
        }

        @Override
        public Dimension fromString(String s) {
            String[] factors = s.split("[xX]");
            if (factors.length != 2) {
                return null ;
            }
            try {
                int w = Integer.parseInt(factors[0].trim());
                int h = Integer.parseInt(factors[1].trim());
                return new Dimension(w, h);
            } catch (NumberFormatException e) {   
                return null ;
            }
        }
    });

    // ...
}

Upvotes: 1

Related Questions