我有几个qml文件,每个文件都在我的应用程序中定义一个屏幕。有时,一个屏幕上的操作应该更改不同屏幕上的项目。现在我通过设置来做到这一点 属性Item buttonId然后执行
for (var i = 0; i < buttonId.parent.children.length; i++) {
buttonId.parent.children[i].state="inactive"
}
是否可以直接访问不同文件中的项目/对象,例如通过他们的身份?
答案 0 :(得分:6)
正如 dtech 所说,你不能访问不同文件中的对象,因为它们还没有对象。
假设您有一个名为BlueSqare.qml
import QtQuick 2.0
Rectangle {
id: root
width: 100
height: 100
color: 'purple'
}
现在你有了main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
width: 300
height: 300
visible: true
Row {
id: rowdi
spacing: 3
Repeater {
model: 3
delegate: BlueSquare {}
}
}
}
你会看到,它创建了我的BlueSquare
中的三个,所以如果我设置root.color = 'blue'
,我想要更改哪一个是未定义的 - 或实际上它不是:因为我有另一个对象使用id: root
中的main.qml
,即ApplicationWindow
,我会将其颜色设置为蓝色。
您可以看到:id
只需要在一个文件中是唯一的,因此您只能通过id
引用此一个文件中的对象。
可以免除此问题:您可以向上移动使用qml文件的文件树并引用它们的ID。
因此,如果您尝试在我的示例中rowdi
中引用BlueSqure
,则会引用安排它们的Row
。这是可能的,因为您可以拥有一个定义明确的规则,您试图通过此id
引用该对象。
如果在文件中找不到id
(此处为:BlueSquare.qml),则尝试引用它,然后它将查找实例化对象的文件(此处为:main.qml)。如果它在那里找到它,搜索就结束了。如果找不到它,它会尝试移动一个文件 - 这在这里是不可能的,就像故事结束的main.qml
一样。
但是如果可能的话应该避免这种情况。也许你想在其他地方重用BlueSquare
,而你没有Row
也恰好拥有id: rowdi
。相反,你应该在实例化中注入引用。
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
width: 300
height: 300
visible: true
Row {
id: rowdi
spacing: 3
property color squareColors: 'blue'
Repeater {
model: 3
delegate: BlueSquare {
color: rowdi.squareColors
}
}
}
}
我们在这里定义了id
rowdi
我们定义它的文件,将数据注入BlueSquare
。
你也可以传递一个QtObject
,它将所有值保存为模型。如果您要更改值,这将特别有用:
// MyModelCountingButton.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
Button {
property QtObject model // Better would be to be more specific the QtObject and have a object that guarantees to have your properties
text: model ? model.count : '-'
onClicked: {
if (model) model.count++
}
}
然后在main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
ApplicationWindow {
id: root
width: 800
height: 600
visible: true
QtObject {
id: myCountingModel
property int count: 0
}
MyModelCountingButton {
id: button1
model: myCountingModel
}
MyModelCountingButton {
id: button2
model: myCountingModel
}
}
现在,您可以使用通用模型更改将影响其他对象的值,而无需引用自己文件之外的内容,从而提高了可重用性。
基本上,uppon实例化你告诉他们他们应该从哪里读取和存储他们的数据,如果这个地方在你的屏幕之间共享,你就赢了。
对于您的问题,最简单的方法是在模型中使用currentIndex
- 属性,为每个屏幕分配一个索引,然后在文件中
// Screen.qml
[...]
Item {
id: root
property int index
property QtObject indexObject
Binding {
target: root
property: 'state'
value: 'inactive'
when: index !== indexObject.currentIndex
}
}
并在main.qml
[...]
ApplicationWindow {
[...]
QtObject {
id: indexObject
property int currentIndex: 0
}
Screen {
index: 0
indexObject: indexObject
}
Screen {
index: 1
indexObject: indexObejct
}
[...]
}
或者您将屏幕视为:
[...]
Item {
id: root
property int index
property int currentIndex
signal turningActive // this must be emitted when you want to have this screen active.
Binding {
target: root
property: 'state'
value: 'inactive'
when: index !== indexObject.currentIndex
}
}
main.qml
[...]
ApplicationWindow {
id: root
[...]
property int currentIndex: 0
Screen {
index: 0
currentIndex: root.currentIndex
onTuringActive: root.currentIndex = 0
}
Screen {
index: 1
currentIndex: root.currentIndex
onTurningActive: root.currentIndex = 1
}
[...]
}
通常,如果只有少数属性,则创建声明其实例化的绑定。如果有大量数字,QtObject
作为模型是有益的
只有当你真的真的确定将在哪个上下文中使用声明的组件时,您才可以考虑引用来自另一个文件的内容(例如,使用parent
文件的根节点或使用需要在另一个文件中解析的id
答案 1 :(得分:4)
您无法访问&#34;不同的qml文件中的对象&#34;除非你有一个qml类型或单例的实例。
只有在尝试访问它的对象在其想要通过id访问的对象的范围内创建时,才可能通过id访问。
您有几个屏幕,只是将它们作为根qml对象的属性公开,然后由于动态范围,它们可以从整个应用程序访问,除非它们被具有相同名称的其他属性遮蔽。