我丰富了一个TextField(显示一个浮动),以便可以通过鼠标滚轮进行更改,同时仍然可以手动编辑。
我找到了与forceActiveFocus
和onClicked
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
文件并且没有定义范围)我不知道该怎么做。任何提示?
我想首先保持定义内联,然后转到单独的文件。
如果您在单独的文件中声明了组件,则可以(应该)省略顶级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
等