重新使用TextField的Component响应车轮事件,并进行信号处理

问题描述 投票:1回答:1

我丰富了一个TextField(显示一个浮动),以便可以通过鼠标滚轮进行更改,同时仍然可以手动编辑。

我找到了与forceActiveFocusonClicked here的怪癖(我希望我可以让所有事件在Qt中传递小部件堆栈)并使用onWheel来更改值(如果这不是最好的方法,请告诉我) :

TextField{
   text: cxxObject.floatAttribute.toString()
   onEditingFinished: { cxxObject.floatAttribute=parseFloat(text); }
   MouseArea{
      anchors.fill: parent
      propagateComposedEvent: true
      onClicked: { parent.forceActiveFocus(); }
      onWheel: { parent.text=parseFloat(parent.text)-.5*wheel.angleDelta.y/120;
         parent.editingFinished();
      }
   }

我想在几个地方重复使用这个组件而不是TextField(没有复制和粘贴),所以我试图像这样声明组件:

Component{
    id: wheeledFloatTextField
    property real initValue: 0.
    property real dWheel: 0.5
    signal editingFinished(real value);
    TextField{
        text: parent.initValue.toString();
        // re-emit signal to the component
        // so that user-defined slot can be defined when re-used
        onEditingFinished: parent.editingFinished(parseFloat(text));
        // validator: ...
        MouseArea{
            anchors.fill: parent
            propagateComposedEvents: true
            onClicked: { parent.forceActiveFocus();  }
            onWheel: {
                parent.text=parseFloat(parent.text)-parent.parent.dWheel*wheel.angleDelta.y/120;
                parent.editingFinished();
            }
        }
    }
}

并重复使用:

Loader{
    sourceComponent: wheeledFloatTextField
    initValue: cxxObject.floatAttribute;
    onEditingFinished: { cxxObject.floatAttribute=value; }
}

然而,我(在使用Component的线路上):

Component objects cannot declare new properties.

怎么了?我收集了一些帖子(如How do you assign a QML Item to a component property in QML and then use that object inside the component?https://developer.blackberry.com/native/documentation/dev/custom_components/index.html)我可能需要在Component.qml这样的东西中包裹Item的内部(如果它是一个单独的Container文件并且没有定义范围)我不知道该怎么做。任何提示?

我想首先保持定义内联,然后转到单独的文件。

qt qml
1个回答
1
投票

如果您在单独的文件中声明了组件,则可以(应该)省略顶级Component。为了最大程度地重用组件,建议将它们声明为单独的文件。 Component不能声明任何属性。它基本上停止了原型状态下的对象创建。如果要配置对象以供以后创建(例如延迟初始化(委托)),这非常有用。 如果你有Component类型的属性并使用myProp: SomeType {...}语法,它将自动创建一个组件。

我认为最好的解决方案是将文本字段放在单独的文件中,并将属性添加到根节点,以便可以自定义。

File1(例如“CustomTextField.qml”)

TextField{
    property real initValue: 0.
    property real dWheel: 0.5
    signal editingFinished(real value);
    text: initValue.toString();
    // re-emit signal to the component
    // so that user-defined slot can be defined when re-used
    onEditingFinished: editingFinished(parseFloat(text));
    // validator: ...
    MouseArea{
        anchors.fill: parent
        propagateComposedEvents: true
        onClicked: { parent.forceActiveFocus();  }
        onWheel: {
            parent.text=parseFloat(parent.text)-parent.parent.dWheel*wheel.angleDelta.y/120;
            parent.editingFinished();
        }
    }
}

然后,您可以以加载器中的所有已知方式重用Component:

Loader {
    sourceComponent: CustomTextField { // Property type is component, so it automatically creates a Component instead of the full-blown object, until it is loaded.
        initValue: 12
        dWheel: 42
    }
    ...
}

或没有装载机

CustomTextField {
    ...
}

当然你可以保持内联,但即便如此,你必须将属性添加到Component中的根元素。

Component {
    id: componentId // only thing you can set besides one Object in a Component
    TextField{
        id: componentRoot // You can't reference this id from outside the Component!!!
        property real initValue: 0.
        property real dWheel: 0.5
        signal editingFinished(real value);
        text: initValue.toString();
        // re-emit signal to the component
        // so that user-defined slot can be defined when re-used
        onEditingFinished: editingFinished(parseFloat(text));
        // validator: ...
        MouseArea{
            anchors.fill: parent
            propagateComposedEvents: true
            onClicked: { parent.forceActiveFocus();  }
            onWheel: {
                parent.text=parseFloat(parent.text)-parent.parent.dWheel*wheel.angleDelta.y/120;
                parent.editingFinished();
            }
        }
    }
}

这有一个缺点,你总是需要一个单独的对象来实例化组件,就像Loader增加了开销并使对象之间的文件中的通信复杂化,因为要解决它,你需要使用:loaderId.item.property,这可能是在查找中很昂贵,你需要确保定义item

© www.soinside.com 2019 - 2024. All rights reserved.