#qt #qml
#qt #qml
Вопрос:
У меня есть гаджет:
class ZScoreParams
{
Q_GADGET
Q_PROPERTY(quint64 lag MEMBER lag);
Q_PROPERTY(qreal threshold MEMBER threshold);
Q_PROPERTY(qreal influence MEMBER influence);
public:
std::size_t lag;
double threshold;
double influence;
};
Q_DECLARE_METATYPE(ZScoreParams)
и свойство объекта типа QVariant
:
Q_PROPERTY(QVariant zscoreParams READ zscoreParams WRITE setZscoreParams NOTIFY zscoreParamsChanged)
его получатель возвращает либо QVariant{}
то, что есть null
в QML, либо QVariant::fromValue(gadget_val)
установщик имеет ту же логику.
Не могу понять, как мне создать диалоговое окно с тремя спин-блоками для редактирования моих параметров ZScoreParams. Каков правильный способ его создания?
Я попытался это ZParamsEdit.qml
:
GridLayout
{
property var params
property var refreshChart: function () {}
signal zparamsChanged()
Component.onCompleted:
{
refreshChart = function ()
{
params.lag = lagEdit.value
params.threshold = thresholdEdit.value
params.influence = influenceEdit.realValue
logTable.debug("qml", JSON.stringify(params))
zparamsChanged()
}
}
Layout.margins: 5
columns: 2
flow: GridLayout.LeftToRight
Label {
text: qsTr("Lag:")
Layout.alignment: Qt.AlignRight
}
SpinBox {
id: lagEdit
value: params.lag
from: 100
to: 1000000
stepSize: 100
editable: true
Layout.alignment: Qt.AlignLeft
onValueChanged: refreshChart()
}
Label {
text: qsTr("Threshold:")
Layout.alignment: Qt.AlignRight
}
SpinBox {
id: thresholdEdit
value: params.threshold
from: 0
to: 100
stepSize: 1
editable: true
Layout.alignment: Qt.AlignLeft
onValueChanged: refreshChart()
}
Label {
text: qsTr("Influence:")
Layout.alignment: Qt.AlignRight
}
RealEdit
{
Layout.alignment: Qt.AlignLeft
id: influenceEdit
decimals: 2
realValue: params.influence
realFrom: 0
realTo: 1.0
realStepSize: 0.1
onValueChanged: refreshChart()
}
}
а затем в main.qml
:
Dialog
{
id: zdlg
ZParamsEdit
{
id: zedit
}
}
IconButton {
icon.source: "images/analyze.svg"
onClicked: {
zedit.params = market.zscoreParams
zdlg.open()
}
}
и получил эффект, которого я не ожидал. Каждый раз, когда изменяется окно редактирования, market.zscoreParams
вызывается параметр установки свойств.
Как ZParamsEdit
сохранить копию моего гаджета и установить значение моего свойства только один раз (для всего гаджета), когда в диалоговом окне нажата кнопка «ОК»?
Также пробовал
JSON.parse(JSON.stringify(market.zscoreParams))
но получил и нечто неожиданное.
ПРАВКА1:
Я, вероятно, нашел уродливое решение с явно определенной функцией, которая создает копию гаджета:
Q_INVOKABLE QVariant cloneZScoreParams(QVariant v)
{
std::optional<ZScoreParams> val;
util::FromVariant(v, val);
return util::ToVariant(val);
}
и затем
globalSettings.cloneZScoreParams(market.zscoreParams)
в QML.
Есть ли что-то лучше в QT?
Комментарии:
1. Почему вы определяете
refreshChart
функцию внутри Component.OnCompleted?2.
refreshChart
Я думаю, @JarMan можно определить напрямую.
Ответ №1:
Если я правильно понимаю вашу проблему, вам просто нужно какое-то локальное свойство / свойства для хранения копии ваших данных, а затем вам нужна какая-то функция, которая записывает эти копии обратно в источник данных.
Вот как я бы изменил ваш код:
GridLayout
{
property var params
// Copy the data into local properties
property lag: params.lag
property threshold: params.threshold
property influence: params.influence
// Only update the local properties when spinboxes change
function refreshChart()
{
lag = lagEdit.value
threshold = thresholdEdit.value
influence = influenceEdit.realValue
zparamsChanged()
}
// Call this when OK button is clicked
function save()
{
params.lag = lag
params.threshold = threshold
params.influence = influence
}
signal zparamsChanged()
...
SpinBox {
id: lagEdit
value: lag
...
onValueChanged: refreshChart()
}
SpinBox {
id: thresholdEdit
value: threshold
...
onValueChanged: refreshChart()
}
RealEdit
{
id: influenceEdit
realValue: influence
...
onValueChanged: refreshChart()
}
}
Обновить:
Чтобы избежать вызова setter 3 раза, вы можете предоставить вызываемую функцию в своем классе C :
Q_INVOKABLE void save(quint64 l, qreal t, qreal i)
{
lag = l;
threshold = t;
influence = i;
}
Теперь функция save () будет выглядеть следующим образом:
function save()
{
params.save(lag, threshold, influence)
}
Комментарии:
1. Мне нужно локальное свойство типа Q_GADGET. Если вы устанавливаете
params
save()
таким образом,zscoreParams
средство установки свойств вызывается три раза, проверьте это самостоятельно с помощью кода на C .