【问题标题】:Show hide component in a repeater在转发器中显示隐藏组件
【发布时间】:2020-10-27 00:20:46
【问题描述】:

我通过加载的组件在转发器中显示了以下一些实例。我正在尝试控制重复组件的可见性

property var modes : [new modeClass("Mode 1", "mode1", noteC1)];

function modeClass(name, representation, note) {
    var active = true;
    this.name = name;
    this.representation = representation;
    this.note = note;
    this.activated = true;

    Object.defineProperty(this, "activated", {
        get : function () {
            return active;
        },
        set : function (newActive) {
            active = newActive;
            if (!active)
                note.selected = false;
            this.dummy = active;
            console.log(name, this.dummy);
        },
        enumerable : true
    });

    this.dummy = active;
}

还有中继器:

// Repeater pour les notes des modes
Repeater {
    id : repModes
    model : modes 
    //delegate : holeComponent - via Loader, to specify the "note" to display
    Loader {
        id : loaderModes
        Binding {
            target : loaderModes.item
            property : "note"
            value : modes[model.index].note
        }
        Binding {
            target : loaderModes.item
            property : "visible"
            value : modes[model.index].activated
        }
        sourceComponent : holeComponent
    }
}

我正在通过某个复选框控制 modeClass 实例的 activated 属性。

我没有设法让可见性工作的属性绑定。 它仅适用于组件的实例化,不会对属性更改做出反应。

我尝试了几种方法来进行绑定:

备选方案 1

带有getter和setter的属性

        Binding {
            target : loaderModes.item
            property : "visible"
            value : modes[model.index].activated
        }

备选方案 2

带有“直接”属性(没有getter,没有setter)

        Binding {
            target : loaderModes.item
            property : "visible"
            value : modes[model.index].dummy
        }

备选方案 3

采用“自下而上”的方法

    Loader {
        id : loaderModes
        ...
        property bool showhide: modes[model.index].activated
        //property bool showhide: modes[model.index].dummy
        sourceComponent : holeComponent
    }

在组件中:

Component {
    id : holeComponent

    Image {
        id : img
        property var note
        visible : showhide

备选方案 4

在模型级别工作:

Repeater {
    id : repModes
    model : modes.filter(function(m) { return m.activated; })
    //model : modes.filter(function(m) { return m.dummy; })

这些都不起作用。 holeComponents 的可见性始终保持在实例化时。

还有其他方法吗?

======================= 27/10 编辑:KISS 版本:

ColumnLayout {
    id : layConfig

    Repeater {
        model : modes
        delegate : CheckBox {
            id : chkConfig
            property var __mode : modes[model.index]
            Layout.alignment : Qt.AlignLeft | Qt.QtAlignBottom
            text : __mode.name + (__mode.activated ? "++" : "--")
            checked : __mode.activated;
            onClicked : {
                console.log("onClik",__mode.name,modelData.name);
                __mode.activated = !__mode.activated;
                console.log("mode.activated ==> ",__mode.activated);
                console.log("modelData.activated ==> ",modelData.activated);
            }
        }

    }
}

我希望当单击复选框时,复选框文本会通过属性绑定自动更改。它不是。我想这可能与property var __mode : modes[model.index] 有关。我应该改用modelData。但是对于modelData,我无法访问更新的底层对象属性。所以它也不起作用。

日志输出:

Debug: onClik Mode 1 Mode 1
Debug: mode.activated ==>  **true**
Debug: modelData.activated ==>  **false**

Debug: onClik Mode 1 Mode 1
Debug: mode.activated ==>  false
Debug: modelData.activated ==>  false

【问题讨论】:

  • 为什么不用common QML 方式定义属性,而是使用Object.defineProperty?您想在中继器中实例化什么组件?无论如何,我看到 KISS principle 不是你最喜欢的 :-)
  • 请尝试绑定到Loadervisible 属性,就像我在这里的回答:stackoverflow.com/questions/64261836/gridlayout-arrangement/…
  • Amfasis 它不起作用。我想问题出在其他地方。请看我的小例子。该问题似乎与访问模型中的对象有关。 @foibis 我承认,我来自一个强类型的世界(java),我无法摆脱我纯粹的 OO 习惯。你有什么建议让它更 KISS?
  • 我是否面临 QML 优化的一些缺点,即在一定程度的深度后停止属性绑定?
  • 我建议你单独设置一个包含uuids和modes/properties的数据结构,var data = [{uuid: 1234, mode: xyz}, {uuid:2382, mode: abc}]。然后,您可以让委托查询数据或在实例化时通过 connect' 功能将正确的数据传递给委托。

标签: qt qml repeater property-binding


【解决方案1】:

我在互联网上发现了这个 hack,并成功地将它应用到我的案例中:

QML trick: force re-evaluation of a property binding

问题在于,qml 仅在重新评估model 时重新评估modelData,它仅在模型中存在明显变化时才会这样做.因此没有检测到模型底层对象的变化。这就是我想要实现的目标。

所以黑客基本上是:

还有中继器:

// Repeater pour les notes des modes
Repeater {
    id : repModes
    model : ready?getActivatedModes():[] // awful hack 
    //delegate : holeComponent - via Loader, to specify the "note" to display
    Loader {
        id : loaderModes
        Binding {
            target : loaderModes.item
            property : "note"
            value : modes[model.index].note
        sourceComponent : holeComponent
    }
}

以及控制复选框的中继器:

Repeater {
    model : __config 
    delegate : CheckBox {
        id : chkConfig
        property var __mode : __config[model.index]
        Layout.alignment : Qt.AlignLeft | Qt.QtAlignBottom
        text : __mode.name
        checked : __mode.activated // init only
        onClicked : {
            __mode.activated = !__mode.activated;
            ready= false; // awful trick to force the refresh
            ready= true;
        }
    }
}

对于 qml,ready=false; ready=true; 是模型中的明显变化,因此 qml 重新评估模型并正确重新绘制所有内容。

【讨论】:

    猜你喜欢
    • 2015-07-06
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 2022-11-28
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多