spinBox value is unbind
-
I have bind the model value to speenBox
SpinBox { id: spinbox Layout.preferredWidth: parent.width * 0.3 from: 0 value: val to: 100 validator: DoubleValidator { bottom: Math.min(spinbox.from, spinbox.to) top: Math.max(spinbox.from, spinbox.to) } onValueChanged: { val = value } }
A loop appeared, but I prevented it as follows:
bool CameraConfigurationSettingsModel::setData(const QModelIndex &index, const QVariant &value, int role) { int row = index.row(); if (row < 0 || row >= settings_.count()) { return false; } CameraConfigurationSetting& setting = settings_[row]; switch (role) { case valueRole: if (setting.GetValue() == value.toDouble()) { // here return false; } setting.SetValue(value.toDouble()); emit dataChanged(index, index); return true; case switchedRole: setting.Switch(); emit dataChanged(index, index); return true; } return false; }
By changing the value in SpeenBox using the up and down arrows, changing the value does not affect the binding, but if I write a value in the field, then after that it will be unlinked. help me please
-
@Idodoqdo this is a standard problem in QML stemming from a conflict between declarative and imperative ways of operation and there are a few ways around it.
One is to use a 2-way binding, see for example this presentation from KDAB about it: link.
Another would be to not set the binding at all, but rather react in slots to both
onValueChanged
(when user changes the value) andonValChanged
(when the model is updated). -
@Idodoqdo said in speenBox value is unbind:
@sierdzio and how will the display understand that the changes relate specifically to this model? Can you please suggest sources that will help me do the 2nd method?
You will set
value
in the slots, so it will be updated in the UI right away. -
how to make Connections if I don't have a model in the component. Only roles?
Item { id:cell RowLayout { spacing: 0 anchors.fill: parent Rectangle { border.color: "black" color: "black" Layout.preferredWidth: parent.width * 0.2 Layout.fillHeight: true Switch { checked: switched anchors.centerIn: parent visible: isHaveSwitch Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter onClicked: { switched = !switched } } } Rectangle { color: "black" Layout.fillWidth: true Layout.fillHeight: true Text { font.bold: true color: "white" text: name anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter } } SpinBox { id: spinbox Layout.preferredWidth: parent.width * 0.3 from: 0 value: val to: 100 validator: DoubleValidator { bottom: Math.min(spinbox.from, spinbox.to) top: Math.max(spinbox.from, spinbox.to) } onValueChanged: { val = value } } } }
-
@Idodoqdo that is a very good question. You can emit a signal in the model and then make
Connections
to the model itself.
Or you can return a QObject from your model (in one of the roles) and have your signal there (and connect to it). -
@Idodoqdo said in spinBox value is unbind:
@sierdzio
in the 2nd case, should the elements of my QAbstractListModel be inherited from QObject?If these are ordinary objects, then only in the first way. ThanksYes, either Q_OBJECT or Q_GADGET, only such objects are visible to QML.
Well ok technically you can return a QVariantMap, too and it "looks" like an object in QML, but it is a hacky solution.
-
All that shouldn't be needed, SpinBox already supports not breaking bindings:
ListModel { id: listModel ListElement { val: 12 } ListElement { val: 33 } } Row { anchors.centerIn: parent spacing: 10 Repeater { model: 2 Column { Repeater { model: listModel SpinBox { id: spinbox editable: true from: 0 to: 50 value: val onValueModified: val = value validator: DoubleValidator { bottom: Math.min(spinbox.from, spinbox.to) top: Math.max(spinbox.from, spinbox.to) } } } } } }
Prefer using the interaction signal
valueModified
than the raw signalvalueChanged
to only catch changes from user interactions and not those from backend bindings like the loop you had before. -