Question is on the title. Let me give an example to make it clear,
let's say I have 2 products and each have different features; therefore, I need to put different items and elements on the Main qml file. So far I have tried controlling elements using Q_PROPERTY
and visible
feature together to check if the parameter has desired value. However, it causes to a total mess, the anchor connections etc. becomes totally uncontrollable because the design also changes, subtly(not critical changes).
So, in short I am looking for a structure that takes a parameter and loads components accordingly.
I also leave an example of what I have done:
In a class,
Q_PROPERTY(int productType READ getproductType WRITE setproductType NOTIFY productType Changed);
And in a qml, I let user to choose which product they have:
Button {
id: id_typeSelector
text: "Type 1"
anchors.left: parent.left
anchors.top: parent.top
onClicked: {
visible: false
object.setproductType(0)
splash.timeout()
}
}
Lastly, on main.qml i determine which component to be showed:
visible: productType === 0
CodePudding user response:
I think what you need is the dynamic loading of a component. One way to do this is through the use of Loaders. The following is an example of how to constraint pipe size input based on the pipe material chosen.
- wood pipes: 3", 5" or 7" diameter
- iron pipe: any diameter
- steel pipes: 3" - 8" diameter
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page {
anchors.fill: parent
ListModel {
id: pipes
ListElement { pipeTypeName: "Wood"; productType: 0 }
ListElement { pipeTypeName: "Iron"; productType: 1 }
ListElement { pipeTypeName: "Steel"; productType: 2 }
}
Frame {
ColumnLayout {
ComboBox {
id: comboBox
model: pipes
textRole: "pipeTypeName"
property int currentProductType: pipes.get(currentIndex).productType ?? -1
}
Loader {
sourceComponent: comboBox.currentProductType === 0 && woodInputComponent
|| comboBox.currentProductType === 1 && ironInputComponent
|| comboBox.currentProductType === 2 && steelInputComponent
|| null
}
}
}
Component {
id: woodInputComponent
RowLayout {
Layout.fillWidth: true
Text { text: qsTr("Wood Pipe Width: ") }
ComboBox { model: [3, 5, 7] }
}
}
Component {
id: ironInputComponent
RowLayout {
Layout.fillWidth: true
TextField { placeholderText: qsTr("Iron Pipe Width") }
}
}
Component {
id: steelInputComponent
RowLayout {
Layout.fillWidth: true
Text { text: qsTr("Steel Pipe Width") }
RangeSlider { from: 3; to: 8 }
}
}
}
You can Try it Online!
In the above example, I used the following way of choosing dynamically loading a component, i.e.
Loader {
sourceComponent: comboBox.currentProductType === 0 && woodInputComponent
|| comboBox.currentProductType === 1 && ironInputComponent
|| comboBox.currentProductType === 2 && steelInputComponent
|| null
}
If your components where declared in their own QML, e.g. WoodInput.qml
, IronInput.qml
and SteelInput.qml
, we can consider refactoring the code to something shorter, e.g.
Loader {
source: pipeTypeName "Input.qml"
}