Em QML, o foco é um conceito que se refere ao controle do teclado e das interações de entrada de usuário, que é atribuído a um componente específico.
Eventos de Teclado em QML
Como o atributo focus está relacionado diretamente ao tratamento de eventos do teclado, então nada mais justo que começarmos por eles.
Eventos de teclado em QML estão relacionados à classe KeyEvent, e para captarmos esse evento podemos utilizar onKeyPressed e onKeyReleased,
Apenas os itens com o foco ativo estarão recebendo os eventos do teclado.
Os eventos de teclado são enviados ao item que está com o foco. Se o item não tratar o evento, ele pode ser propagado para outros itens mais externos, ou do mesmo FocusScope.
Aqui temos um exemplo prático:
Rectangle {
width: 200
height: 200
focus: true // Necessário para receber eventos de teclado
onKeyPressed: {
console.log("Key pressed:", event.key)
}
}
Basicamente sempre que temos uma ação no teclado o QML verifica se existe algum elemento com o foco ativo, e envia uma notificação de que essa tecla foi pressionada, caso exista, um tratamento para ela será executado,caso contrário irá apenas ignorar.
Ordem de declaração e Hierarquia
Ao instanciar um componente no QML o primeiro item do seu sistema com o atributo "focus: true" receberá o foco na sua aplicação, e assim este itém estará aberto para receber eventos de teclado, e sim praticamente qualquer componente pode estar habilitado a receber
Caso você possua vários componentes em um mesmo nivél hierárquico cada um deles com o atributo de "focus: true" apenas o ultimo componente declarado recebe o foco e habilita eventos de usuário.
Vamos supor que você tenha uma tela de cadastro de usuário com três inputs, sendo eles nome, telefone, endereço, você pode se sentir atraído a declarar seus componentes "focus: true" como no exemplo abaixo.
Item {
TextInput {
id: textInput1
width: 100; height: 100
color: "lightblue"
text: "Input 1"
focus: true
}
TextInput {
id: textInput2
width: 100; height: 100
x: 120
color: "lightgreen"
text: "Input 2"
focus: true
}
TextInput {
id: textInput3
width: 100; height: 100
x: 240
color: "lightcoral"
text: "Input 3"
focus: true
}
}
apesar do QML tratar-se de uma linguagem declarativa e não estruturada, seus componentes seguem uma ordem de hierarquia e construção, ou seja, os componentes são montados e sobrepostos, na ordem em que foram declarados em seu arquivo.
O item com o foco habilitado nesse momento é textInput3.
Esse tipo de equivoco raramente irá acontecer, exceto por alguma distração na hora da criação do componente.
Propriedades, métodos
Uma parte fundamental para o entendimento, e prevenção de eventuais bugs, é entender o papel dos atributos e métodos relacionados ao focus;
focus
É uma propriedade booleana que pode ser definida em seu item, ela pode não refletir o estado atual dele, ou seja, você pode declarar "focus: true" dentro de seu item e mesmo assim ele não receber o foco para si, essa propriedade está mais relacionada a sua intenção de dar foco ao seu componente, e dependendo do contexto em que ele for construido receberá ou não o foco ativo.
TextInput {
id: myInput
width: 100
height: 40
text: "Input Field"
focus: true // Tentará receber o foco automaticamente
}
activeFocus
Também é uma propriedade booleana, porém ao contrário da propriedade focus, ela retorna um valor booleano, esse valor é o estado do foco atual do seu item, ou seja se seu componente realmente estiver com foco ela retornará "true", caso contrário irá retornar "false", geralmente é utilizada em métodos para definir alguns atributos, ou para fins de depuração
Rectangle {
width: 100
height: 100
color: activeFocus ? "green" : "red" // Muda a cor com base no estado do foco ativo
focus: true
}
focusItem
Esta é outra propriedade booleana que refere-se ao item que possui o foco atual, ou seja retorna o item que realmente está com o foco naquele momento.
forceActiveFocus()
Este método solicita que o item receba o foco imediatamente, mesmo que outros itens estejam com o foco.
FocusScope
Trata-se de um componente que gerencia o foco de seus filhos, a fim de evitar comportamentos inexperado.
Quando eu direciono um foco a um FocusScope,ele garante que os componentes filhos receberão seu foco corretamente.
No exemplo abaixo iremos criar um Item com dois imputs,e em seguida iremos adicionar dois itens que acabamos de criar.
Item{
id: DoubleInputs
anchors.right: parent.right
anchors.bottom: parent.bottom
width: 200
height: 100
Row{
TextInput {
id: input1
width: 100
height: 40
text: "Input 3"
}
TextInput {
id: input2
width: 100
height: 40
x: 120
text: "Input 4"
focus: true
}
}
}
ApplicationWindow {
visible: true
width: 400
height: 300
DoubleInputs {
id:Double1
focus:true
anchors.centerIn: parent
KeyNavigationDown:Double2
}
DoubleInputs {
id:Double2
anchors.centerIn: parent
}
}
Neste exemplo teremos quatro inputs, A aplicação iniciará com o foco no Double1, mas ao clicar com a seta que indica "para baixo" no seu teclado, o foco muda para Double2, e eu quero que ao clicar com a seta para baixo a minha aplicação printe no console hello World
TextInput {
id: input2
width: 100
height: 40
x: 120
text: "Input 4"
focus: true
KeyNavigationUp: console.log("hello World");
}
Porém mesmo com o input2 estando com o focus atribuido como true, ele não irá receber o foco, pois o componente Item não tem a capacidade de gerenciar o foco de seus filhos, e quando apertamos a tecla "para baixo" o foco é dado para o componente Double2, e não ao seu filho TextInput, e como o Double2 não possui nenhum tratamento para os inputs to teclado, nada irá acontecer, e para resolver esse problema é bem simples. Basta trocar Item por FocusScope
FocusScope{
id: DoubleInputs
anchors.right: parent.right
anchors.bottom: parent.bottom
width: 200
height: 100
Row{
TextInput {
id: input1
width: 100
height: 40
text: "Input 3"
}
TextInput {
id: input2
width: 100
height: 40
x: 120
text: "Input 4"
focus: true
}
}
}
Assim ao receber a atribuição de foco, o FocusScope irá redistribuir o foco para seus filhos de acordo com a lógica implementada por você. Lembrando que o último componente com "focus: true" é que irá realmente receber a primeira atribuição da propriedade.
Conclusão
Para ter um melhor proveito e evitar possiveis bugs relacionados aos inputs periféricos da sua aplicação, é extremamente importante dominar os conceitos do foco em componentes do QML.
Top comments (0)