Introdução ao Projeto
Este documento detalha a implementação de um aplicativo completo que utiliza o componente QComboBox em um ambiente HarmonyOS. A aplicação demonstra a seleção em cascata entre províncias e cidades, evidenciando a aplicação prática do Qt Quick Controls 2.15 nesta plataforma. A estrutura inclui entrada de texto, seleções em dois níveis e funcionalidades de exibição e limpeza de dados, com suporte a interações por toque.
Pontos Técnicos Essenciais
1. Ponto de Entrada para HarmonyOS: qtmain()
Ponto Crítico: Em dispositivos HarmonyOS, o ponto de entrada deve ser a função qtmain() em vez de main().
// Abordagem Correta para HarmonyOS
extern "C" int qtmain(int argc, char **argv)
{
QGuiApplication application(argc, argv);
QQmlApplicationEngine qmlEngine;
qmlEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return application.exec();
}
// Abordagem Incorreta (padrão desktop)
int main(int argc, char *argv[])
{
// Falhará ao iniciar no HarmonyOS
}
Motivo: O HarmonyOS carrega a aplicação Qt como uma biblioteca compartilhada (.so), e seu ciclo de vida é gerenciado pela Ability do sistema. A função qtmain() é o ponto de entrada padrão para o plugin Qt do HarmonyOS.
2. Configuração do Formato de Superfície OpenGL ES
Ponto Crítico: A configuração do QSurfaceFormat deve ocorrer antes da instanciação do QGuiApplication.
// Etapa 1: Configurar o formato de superfície OpenGL ES
QSurfaceFormat surfaceConfig;
surfaceConfig.setAlphaBufferSize(8);
surfaceConfig.setRedBufferSize(8);
surfaceConfig.setGreenBufferSize(8);
surfaceConfig.setBlueBufferSize(8);
surfaceConfig.setDepthBufferSize(24);
surfaceConfig.setStencilBufferSize(8);
surfaceConfig.setRenderableType(QSurfaceFormat::OpenGLES);
surfaceConfig.setVersion(3, 0);
// Definir como formato padrão antes de criar a aplicação
QSurfaceFormat::setDefaultFormat(surfaceConfig);
// Etapa 2: Criar a instância da aplicação Qt
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QGuiApplication app(argc, argv);
3. Utilização do Componente QML ComboBox
3.1 Definição Básica do ComboBox
ComboBox {
id: seletorRegiao
width: parent.width - 180
height: 100
model: listaRegioes
enabled: true
font.pixelSize: 40
z: 10
hoverEnabled: false
focusPolicy: Qt.ClickFocus
popup {
width: seletorRegiao.width
y: seletorRegiao.height
z: 1000
}
delegate: ItemDelegate {
width: seletorRegiao.width
height: 80
text: modelData
font.pixelSize: 40
highlighted: seletorRegiao.highlightedIndex === index
padding: 10
}
onCurrentIndexChanged: {
console.log("Seleção de região alterada:", currentIndex)
}
}
3.2 Implementação da Seleção em Cascata
property var listaRegioes: ["Província A", "Província B", "Província C"]
ListModel {
id: modeloCidades
ListElement { idRegiao: 0; nomeCidade: "Capital X" }
ListElement { idRegiao: 0; nomeCidade: "Município Y" }
ListElement { idRegiao: 1; nomeCidade: "Centro Z" }
}
property int regiaoSelecionada: 0
property var cidadesDisponiveis: []
function atualizarListaCidades() {
var cidadesFiltradas = []
for (var i = 0; i < modeloCidades.count; i++) {
var item = modeloCidades.get(i)
if (item && item.idRegiao === regiaoSelecionada) {
cidadesFiltradas.push(item.nomeCidade)
}
}
cidadesDisponiveis = cidadesFiltradas
seletorCidades.model = cidadesDisponiveis
if (cidadesDisponiveis.length > 0) {
seletorCidades.currentIndex = 0
}
}
ComboBox {
id: seletorRegiao
onCurrentIndexChanged: {
if (currentIndex >= 0) {
regiaoSelecionada = currentIndex
atualizarListaCidades()
}
}
}
3.3 Configuração Crucional para o Dispositivo
No arquivo entry/src/main/module.json5, o campo deviceTypes deve incluir "2in1".
{
"module": {
"name": "entry",
"type": "entry",
"deviceTypes": [
"default",
"tablet",
"2in1" // Obrigatório para dispositivos PC/2-em-1
]
}
}
Motivo: Dispositivos como o MateBook são identificados como tipo "2in1". A omissão deste valor impede que a ferramenta de empacotamento loaclize corretamente o arquivo de configuração, resultando em erro de construção.
Soluções para Problemas Comuns
Problema 1: Falta de Resposta a Interações
Sintomas: A interface é renderizada, mas cliques e toques não produzem efeito.
Causas: Janela não ativada, ciclo de eventos não iniciado ou problemas de gerenciamento de foco.
Solução: Garanta a ativação da janela.
// Em main.cpp
QQuickWindow* mainWindow = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
if (mainWindow) {
mainWindow->show();
mainWindow->raise();
mainWindow->requestActivate();
}
// Em main.qml
Component.onCompleted: {
janelaPrincipal.show()
janelaPrincipal.requestActivate()
}
Problema 2: ComboBox Não Exibe Menu Suspenso
Causas Comuns: Um MouseArea sobreposto intercepta os eventos, hoverEnabled está true ou o z-index do popup está incorreto.
Solução:
ComboBox {
hoverEnabled: false
focusPolicy: Qt.ClickFocus
popup {
z: 1000
}
// Evite adicionar MouseArea sobre o ComboBox.
}
Problema 3: Tela em Branco ou Preto
Causas: Falha no carregamento do QML, erro na configuração do OpenGL ES ou uso de um componente Window incompatível.
Solução: Verifique o carregamento do QML e utilize ApplicationWindow para melhor suporte.
ApplicationWindow {
id: raiz
visible: true
Component.onCompleted: raiz.requestActivate()
}
Melhores Práticas
- Gerenciamento de Foco: Use
Qt.ClickFocuse garanta a ativação da janela. - Otimização para Toque: Defina
hoverEnabled: falsee garanta alturas mínimas de 44 pixels para itens. - Manuseio de Eventos: Permita que os controles processem seus próprios eventos; evite
MouseAreadesnecessários. - Modelos de Dados: Utilize
ListModelpara dados estruturados e atualize omodeldo ComboBox programaticamente.
Estrutura e Configuração do Projeto
QComboBox/
├── entry/
│ ├── src/main/
│ │ ├── cpp/ (main.cpp, CMakeLists.txt)
│ │ ├── module.json5 (contém "2in1" em deviceTypes)
│ │ └── resources/ (main.qml, qml.qrc)
│ └── build-profile.json5
└── CMakeLists.txt (configuração raiz)
Exemplo de CMakeLists.txt
cmake_minimum_required(VERSION 3.5.0)
project(QtHarmonySample)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2)
add_library(entry SHARED main.cpp qml.qrc)
target_link_libraries(entry PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
Qt6::QuickControls2
QOpenHarmonyPlatformIntegrationPlugin
)