guia - ¿Cómo definir una “plantilla” con marcadores de posición secundarios en QML?
qgis español (5)
En definitiva (para mostrar la idea):
import QtQuick 1.1
Item {
width: 200
height: 100
//<-- the client can set the placeholder content here
property Item contents: Rectangle {
anchors.fill: parent
anchors.margins: 25
color: "red"
}
Rectangle {
id: container
anchors.fill: parent
radius: 10
color: "gray"
//<-- where the placeholder should be inserted
}
Component.onCompleted: {
contents.parent = container
}
}
Versión algo más larga (reasignación de contenidos de soporte):
import QtQuick 1.1
Item {
width: 200
height: 100
//<-- the client can set the placeholder content here
property Item contents: Rectangle {
//anchors can be "presupplied", or set within the insertion code
//anchors.fill: parent
//anchors.margins: 25
color: "red"
}
Rectangle {
id: container
anchors.fill: parent
radius: 10
color: "gray"
//<-- where the placeholder should be inserted
//Item {
// id: placeholder
//}
}
//"__" means private by QML convention
function __insertContents() {
// move the contents into the placeholder...
contents.parent = container
contents.anchors.fill = container
contents.anchors.margins = 25
}
onContentsChanged: {
if (contents !== null)
__insertContents()
}
Component.onCompleted: {
__insertContents()
}
}
Espero que esto ayude :)
Realmente me gusta QML. Me gusta cómo puedo definir los componentes (comparables a las clases) y sus propiedades, e instanciarlos desde otro lugar (comparable a los objetos).
Puedo definir, digamos, un botón, con cierto aspecto y un texto de etiqueta en él. Esto se podría hacer, por ejemplo, usando esta definición de componente ( Button.qml
):
Item {
id: button
property string label
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Text {
anchors.centerIn: parent
font.pixelSize: 20
text: button.label
color: "white"
}
}
}
e instanciados en este archivo principal ( main.qml
):
Rectangle {
width: 300
height: 200
Button {
anchors.centerIn: parent
anchors.margins: 50
label: "Hello button!"
}
}
Pero veo la siguiente restricción: solo puedo definir una plantilla de botón con algunas propiedades , no con algún marcador de posición . Todos los hijos definidos en la instancia serán hijos directos, al menos por defecto, y quiero cambiar este comportamiento.
Digamos que quiero colocar un elemento (digamos una imagen, pero no quiero decirle a la definición de Button
que será una imagen) en el botón. Me imagino algo como esto:
Item {
id: button
property Item contents <-- the client can set the placeholder content here
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
Component.onCompleted: {
// move the contents into the placeholder...
}
}
¿Cómo puedo conseguir esto? No sé si usar Component.onCompleted
es la forma correcta. Tenga en cuenta que, en mi caso, el contenido nunca cambiará después (al menos en mi diseño actual de la aplicación ...).
Además, quiero que el anclaje funcione dentro del marcador de posición. Por ejemplo, si defino el contenido como un elemento de Texto, centrado en su elemento primario (que primero será la propia plantilla). Luego mi código mueve esta instancia de Texto al marcador de posición y los anclajes primarios deben ser los del elemento marcador de posición, no el elemento de la plantilla.
En realidad, la respuesta correcta de lo que he escuchado es usar un cargador QML para lograr lo que quieres.
[habiendo dicho eso; Aún no lo he intentado pero está en mi lista de intentos a corto plazo y parece bastante sencillo]
Además, busque para otras preguntas sobre el "Cargador QML" ya que hay un número que lo ayudará a comenzar.
Encontré una respuesta mucho mejor a esta pregunta, sugerida en una presentación de Qt Developer Days 2011 "Qt Quick Best Practices and Design Patterns" .
Usan el default property alias ...
para asignar alias a los elementos secundarios a cualquier propiedad de cualquier elemento. Si no desea asignar un alias a los hijos, pero asigne un nombre a la propiedad de alias, simplemente elimine el default
. (Los hijos literales son por definición de QML el valor de la propiedad predeterminada).
Item {
id: button
default property alias contents: placeholder.children
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
}
Necro responde en caso de que alguien más termine aquí como yo.
En Qt5, en algún lugar a lo largo de la línea, la propiedad predeterminada se convirtió en " data " y no en "hijos". Esto hace posible agregar otros tipos de objeto que "Elemento". Por ejemplo, también se pueden agregar conexiones (para responder a mi propia pregunta arriba)
Así que en Qt5 debes hacer:
Item {
id: button
default property alias contents: placeholder.data
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
}
Tenga en cuenta: placeholder.data
lugar de placeholder.children
También tenga en cuenta que no tiene que usar el contents
nombre de alias; esto puede ser lo que quiera. Un ejemplo:
Item {
id: button
default property alias foo: placeholder.data
...
}
Puede mover los elementos (si desea admitir varios elementos dentro del marcador de posición) utilizando este código:
property list<Item> contents
Component.onCompleted: {
var contentItems = [];
for(var i = 0; i < contents.length; ++i)
contentItems.push(contents[i]);
placeholder.children = contentItems;
}
Tenga en cuenta que no tiene que proporcionar una lista de elementos para la propiedad de contenido, ya que el motor QML también aceptará valores únicos para las propiedades de lista.