Em QML, o sistema de coordenadas é baseado em um plano cartesiano bidimensional com pixels como unidade. A origem (0,0) está no canto superior esquerdo da tela, onde o eixo X se estende para a direita e o eixo Y para baixo. Cada elemento QML, como Rectangle ou Image, possui seu próprio sistema de coordenadas local, com a origem em seu canto superior esquerdo.
Ao definir posições usando as propriedades x e y, você está trabalhando com coordenadas relativas ao elemento pai, não com coordneadas asbolutas da tela. Por exemplo:
Rectangle {
width: 120;
height: 120;
x: 40;
y: 60;
color: "green";
}
Essa abordagem pode ser viável em layouts simples, mas se torna complexa com múltiplos elementos ou interfaces responsivas. Para uma gestão mais eficiente, utiliza-se o sistema de âncoras (anchors), que permite vincular bordas ou centros de elementos entre si, promovendo layouts adaptáveis.
Veja um exemplo de aplicação de âncoras para posicionar elementos dentro de uma janela:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true;
width: 380;
height: 220;
title: "Exemplo de Âncoras";
Rectangle {
id: caixaA;
width: 160;
height: 70;
color: "orange";
border.color: "darkred";
anchors.top: parent.top;
anchors.rightMargin: 15;
}
Rectangle {
id: caixaB;
width: 160;
height: 70;
color: "orange";
border.color: "darkred";
anchors.top: parent.top;
anchors.left: caixaA.right + 25;
anchors.right: parent.right;
}
Text {
id: rotulo;
text: "Bem-vindo ao QML!";
font.pixelSize: 22;
anchors.top: caixaA.bottom;
anchors.topMargin: 10;
}
Button {
id: botao;
text: "Pressione";
anchors.top: rotulo.bottom;
anchors.bottom: parent.bottom;
anchors.topMargin: 18;
onClicked: {
console.log("Ação do botão");
}
}
}
Nesse código, os elementos são organizados vertical e horizontalmente usando âncoras, sem depender de coordenadas explícitas. O primeiro retângulo (caixaA) é ancorado ao topo do pai, enquanto o segundo (caixaB) é posicionado à direita do primeiro, com um deslocamento. O texto e o botão são subsequentemente ancorados abaixo dos retângulos.
As âncoras oferecem diversas propriedades para controle de layout:
- Âncoras de borda:
anchors.left,anchors.right,anchors.top,anchors.bottom— vinculam bordas do elemento a bordas de outro elemento. - Margens:
anchors.leftMargin,anchors.rightMargin,anchors.topMargin,anchors.bottomMargin— adicionam deslocamentos após o posicionamento pela âncora. - Âncoras de centro:
anchors.horizontalCenter,anchors.verticalCenter,anchors.centerIn— alinham centros de elementos. - Preenchimento:
anchors.fill— faz o elemento ocupar todo o espaço do elemento de referência.
Considere outro exemplo com múltiplas âncoras:
import QtQuick 2.0
Rectangle {
id: base;
width: 280;
height: 280;
color: "lightgray";
Rectangle {
id: interno;
width: 120;
height: 120;
color: "steelblue";
anchors.right: base.right;
anchors.bottom: base.bottom;
anchors.rightMargin: 35;
anchors.bottomMargin: 35;
anchors.horizontalCenter: base.horizontalCenter;
anchors.verticalCenter: base.verticalCenter;
}
}
Aqui, o retângulo interno é posicionado usando âncoras de borda e centro. As âncoras de borda (right e bottom) definem a posição inicial, enquanto as âncoras de centro ajustam o alinhamento. As margens aplicam deslocamentos adicionais.
Ao combinar âncoras, surgem prioridades que afetam o layout:
- Âncoras explícitas têm precedência sobre regras implícitas, como propriedades
widthouheight. - Em caso de conflito, âncoras de borda geralmente superam âncoras de centro.
- A propriedade
anchors.fillsobrepõe outras configurações de âncora, pois visa preencher completamente o elemento de referência. - Margens são aplicadas após o posicionamento pelas âncoras, ajustando deslocamentos sem alterar a relação base.
Por exemplo:
Rectangle {
width: 100;
height: 100;
color: "yellow";
Rectangle {
id: filho;
anchors.left: parent.left;
anchors.leftMargin: 25;
color: "purple";
}
}
Neste caso, a posição horizontal de filho é determinada pela âncora left, com um deslocamento de 25 pixels aplicado pela margem.
Em situações onde âncoras conflitam, como ao definir anchors.top e anchors.bottom simultaneamente, a altura do elemento será calculada com base nas âncoras, ignorando a propriedade height:
Rectangle {
width: 100;
height: 100;
color: "red";
Rectangle {
id: expansivo;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
color: "blue";
}
}
Aqui, expansivo esticará para preencher verticalmente o pai, independentemente de qualquer valor definido para height.