如何获得涉及QML MouseAreas的声明性双向绑定? [英] How do I have declarative, bidirectional bindings involving QML MouseAreas?

查看:183
本文介绍了如何获得涉及QML MouseAreas的声明性双向绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个具有转盘和自定义控件的QML UI.自定义控件基本上是带有MouseArea的进度条,允许用户单击它来设置值.正如Qt的属性绑定文档指出的那样,MouseArea单击处理程序中的Javascript分配给自定义控件的值,我将失去它和拨盘之间的声明性绑定.

I've created a QML UI that has a dial and a custom control. The custom control is basically a progress bar with a MouseArea to allow the user to set the value by clicking it. As Qt's property binding docs point out, as soon as I assign to the custom control's value from Javascript in the MouseArea click handler, I lose the declarative binding between it and the dial.

在QML层次结构中,是否可以使此绑定双向,甚至更好,以将两个控件的值链接到单个控件上的单个值?并且可以使用声明性语法来做到这一点,这样我就不会在每个控件中都有复杂的事件处理程序代码吗?

Is it possible to make this binding bidirectional, or even better, to link the values of both controls to a single value above both of them in the QML hierarchy? And is it possible to do this with declarative syntax so I don't have complex event handler code in every control?

import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtQuick.Shapes 1.0


Window {
    id: window
    visible: true
    width: 800
    height: 200

    readonly property int range: 10

    RowLayout {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        spacing: 5

        Dial {
            id: dial1
            live: true
            from: 0
            to: window.range
            stepSize: 1
            snapMode: Dial.SnapAlways
        }

        Control {
            id: dut

            implicitWidth: 200
            implicitHeight: 50

            property int range: window.range
            property int value: dial1.value

            onValueChanged: {
                console.log("New value: " + value);
            }

            Rectangle {
                width: parent.width
                height: parent.height
                color: Qt.rgba(0,0,0,0)
                border.color: Qt.rgba(0,0,0,1)
                border.width: 1
            }

            Rectangle {
                width: parent.width * dut.value/dut.range
                height: parent.height
                color: Qt.rgba(0,0,0,1)
            }

            MouseArea {
                anchors.fill: parent

                onClicked: {
                    dut.value = Math.round(mouseX/width * dut.range);
                }
            }
        }
    }
}

请注意,如果我颠倒关系,即.具有dial1.value: dut.value,则绑定不会中断(尽管它不是双向的).

Note that if I reverse the relationship ie. have dial1.value: dut.value, then the binding isn't broken (although it's not quite bidirectional).

我意识到这个示例从根本上重塑了滚动条,但是我正在尝试以更复杂的控件进行工作,对于这些控件,值之间的声明性关系将使生活变得更加轻松.

I realise that this example basically reinvents the scrollbar, but I'm trying to work my way up to more complex controls, for which declarative relationships between values would make life much easier.

评论中的阐述:我不了解,但想要了解的是如何对其他QML组件进行处理.例如,使用Dial,我可以将其value属性设置为绑定到其他组件的属性,并且单击表盘不会删除该绑定.我不必迷上它的鼠标事件就可以做到这一点.尽管从源头上了解了如何完成此操作,但我实际上离了解它还很近.

Elaboration from a comment: What I don't understand, but want to, is how it's done for other QML components. For example, with a Dial I can set its value property to be bound to some other component's property, and clicking on the dial doesn't remove that binding. I don't have to hook into its mouse events to do that. Despite looking through the source for how this is done, I'm not really any closer to understanding it.

关于QML中的双向属性绑定还有其他问题,但是我无法将其应用于我的问题,因为(a)我真的非常想要声明性的东西,并且(b)MouseArea属性和事件似乎不适用于Binding对象(例如,我无法弄清楚如何整合这两种方法).

There are other questions about bidirectional property bindings in QML, but I haven't been able to apply them to my problem because (a) I really, really want something declarative, and (b) the MouseArea properties and events don't seem to work well with Binding objects (as in, I can't figure out how to integrate the two things).

推荐答案

我会这样做:

import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.2
import QtQuick.Shapes 1.0


Window {
    id: window
    visible: true
    width: 800
    height: 200

    readonly property int range: 10
    property int commonValue

    RowLayout {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        spacing: 5

        Dial {
            id: dial1
            live: true
            from: 0
            to: window.range
            stepSize: 1
            snapMode: Dial.SnapAlways
            onValueChanged: {
                commonValue = dial1.value
                console.log("New value: " + value);
            }
        }
        Rectangle {
            width: 200
            height: 50
            color: Qt.rgba(0,0,0,0)
            border.color: Qt.rgba(0,0,0,1)
            border.width: 1

            MouseArea {
                anchors.fill: parent

                onClicked: {
                    commonValue = Math.round(mouseX/width * window.range)
                    dial1.value = commonValue
                }
            }

            Rectangle {
                width: parent.width * window.commonValue/window.range
                height: parent.height
                color: Qt.rgba(0,0,0,1)
            }
        }
    }
}

这篇关于如何获得涉及QML MouseAreas的声明性双向绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆