SegmentedControl to Control a DropDown

Elements/Components Used:

DropDown, SegmentedControl, Label

BlackBerry 10 Cascades SegmentedControl DropDown

In the first app I created in Cascades, a portion of it requires the user to enter a measurement. So I had a DropDown box of different measurements, all in feet.  I tied that to a C++ function and it ran its magic to get my desired output.  Then I realized I never accounted if the user wanted to enter measurements in something other than feet, such as meters. (Being an American we don't use such things but figured this app may go worldwide.)  I knew I could adjust the C++ to handle it but then I wondered if I could have Cascades/QML show an interface where the user thought they were entering meters but the C++ still read it as feet.  So I did just that, and I'll explain how.

First set up the basic environment of a SegmentedControl (id: tog), with two options: "Feet" (id: feetoption) and "Meters" (id: meteroption). Below that is DropDown (id: dd1) with 4 options (id's not necessary for these).  The four options of the DropDown are 12, 15, 40 and 50 (12ft = 40m and 15ft = 50m, these make four good testing points, my actual list for the app was much longer but the same principles apply).

 

Page {
    content: Container {
        Container {
            SegmentedControl {
                id: tog
                Option {
                    id: feetoption
                    text: "Feet"
                    onSelectedChanged: {
                    }
                    selected: true
                }
                Option {
                    id: meteroption
                    text: "Meters"
                    onSelectedChanged: {
                    }
                }
                preferredWidth: 650.0
            }
            DropDown {
                id: dd1
                title: "measure (ft)"
                onSelectedIndexChanged: {
                }
                Option {
                    text: "12"
                    value: 12
                }
                Option {
                    text: "15"
                    value: 15
                }
                Option {
                    text: "40"
                    value: 40
                }
                Option {
                    text: "50"
                    value: 50
                }
            }
        }
    }
}

 

Now it is time to have JavaScript in the QML rework the numbers to produce the desired output. For the sake of showing the calculation I will output it to a Label (id: label 1).  However for my actual case where I send this value to C++, I outputted it to a variable that the C++ called on for it's function.

This Label will show the value in feet regardless of whether the user thinks they are entering feet or entering meters. (For testing I have label2 show the meters conversion.)  I accomplished this with using the "onSelectedChanged" signal from inside of each of the options of the SegmentedControl as well as in the DropDown control. 

That makes a total of 3 "onSelectedChanged" signals, that all do similar things.  This was done because the numbers need to recompute at three different occasions: 1. Users switches from ft to m, 2. User switches from m to ft, and 3. User selects a new option from the DropDown.

Our onSelectedChanges for proper conversion should look like the following:

onSelectedChanged for feetoption and meteroption:

 

                    onSelectedChanged: {
                        var dropvalue = dd1.at(dd1.selectedIndex).value;
                        if (feetoption.selected == true) {
                            label1.text = "ft = " + dropvalue;
                            label2.text = "m = " + dropvalue / 3.28084;
                        } else {
                            label1.text = "ft = " + dropvalue * 3.28084;
                            label2.text = "m = " + dropvalue;
                        }
                    }

 

onSelectedChanged for dd1:

 

                onSelectedIndexChanged: {
                    var dropvalue = dd1.at(dd1.selectedIndex).value;
                    if (feetoption.selected == true) {
                        label1.text = "ft = " + dropvalue;
                        label2.text = "m = " + dropvalue / 3.28084;
                    } else {
                        label1.text = "ft = " + dropvalue * 3.28084;
                        label2.text = "m = " + dropvalue;
                    }
                }

 

***SIDE NOTE: To call a DropDown's selected value you must create a variable of the form "var nameyourvariable = dropdownID.at(dropdownID.selectedIndex).propertyofdropdownoption" such as:

 

var dropvalue = dd1.at(dd1.selectedIndex).value;

 

End of NOTE.***

Last I added an additional Boolean statement to each signal to also change the title text of the DropDown between "measure (ft)" and "measure (m)" to give the user feedback that the DropDown has in fact changed and those values now represent the units they intend.

 

if (feetoption.selected == true) {
     dd1.title = "measure (ft)";
 } else {
     dd1.title = "measure (m)";
         }

 

Now running the app everything should behave as I have explained above and I didn't have to change my C++ to accept meters and feet.  As always full code of the main.qml file below. Enjoy.

-Brian

main.qml:

 

import bb.cascades 1.0

Page {
    content: Container {
        Container {
            SegmentedControl {
                id: tog
                Option {
                    id: feetoption
                    text: "Feet"
                    onSelectedChanged: {
                        if (feetoption.selected == true) {
                            dd1.title = "measure (ft)";
                        } else {
                            dd1.title = "measure (m)";
                        }
                        var dropvalue = dd1.at(dd1.selectedIndex).value;
                        if (feetoption.selected == true) {
                            label1.text = "ft = " + dropvalue;
                            label2.text = "m = " + dropvalue / 3.28084;
                        } else {
                            label1.text = "ft = " + dropvalue * 3.28084;
                            label2.text = "m = " + dropvalue;
                        }
                    }
                    selected: true
                }
                Option {
                    id: meteroption
                    text: "Meters"
                    onSelectedChanged: {
                        if (feetoption.selected == true) {
                            dd1.title = "measure (ft)";
                        } else {
                            dd1.title = "measure (m)";
                        }
                        var dropvalue = dd1.at(dd1.selectedIndex).value;
                        if (feetoption.selected == true) {
                            label1.text = "ft = " + dropvalue;
                            label2.text = "m = " + dropvalue / 3.28084;
                        } else {
                            label1.text = "ft = " + dropvalue * 3.28084;
                            label2.text = "m = " + dropvalue;
                        }
                    }
                }
                onSelectedIndexChanged: {
                    var choosen1 = tog.selectedValue()
                    console.debug("Selected value: " + choosen1);
                }
                preferredWidth: 650.0
            }
            DropDown {
                id: dd1
                title: "measure (ft)"
                onSelectedIndexChanged: {
                    var dropvalue = dd1.at(dd1.selectedIndex).value;
                    if (feetoption.selected == true) {
                        label1.text = "ft = " + dropvalue;
                        label2.text = "m = " + dropvalue / 3.28084;
                    } else {
                        label1.text = "ft = " + dropvalue * 3.28084;
                        label2.text = "m = " + dropvalue;
                    }
                }
                Option {
                    text: "12"
                    value: 12
                }
                Option {
                    text: "15"
                    value: 15
                }
                Option {
                    text: "40"
                    value: 40
                }
                Option {
                    text: "50"
                    value: 50
                }
            }
            Label {
                id: label1
                text: ""
            }
            Label {
                id: label2
                text: ""
            }
        }
    }
}

 

done.