Ao desenvolver interfaces complexas com o Qt, é comum a necessidade de integrar múltiplos arquivos .ui criados no Qt Designer em uma classe principal. Um desafio frequente é garantir que determinadas janelas auxiliares permaneçam à frente (Always on Top) ou funcionem como diálogos controlados manualmente sem bloquear completamente a thread principal.
Quando um arquivo .ui é compilado, o uic gera um cabeçalho correspondente (ex: ui_form_ajustes.h). Esse arquivo define uma classe dentro do namespace Ui que deve ser instanciada para que os componentes visuais sejam acessíveis via código C++.
Estrutura do Cabeçalho (janelaprincipal.h)
Para gerenciar múltiplos widgets customizados, declaramos os ponteiros para as interfaces geradas e os widgets que servirão como containers para essas interfaces.
#ifndef JANELAPRINCIPAL_H
#define JANELAPRINCIPAL_H
#include <QMainWindow>
#include <QWidget>
namespace Ui {
class JanelaPrincipal;
class FormConfig;
class FormStatus;
}
class JanelaPrincipal : public QMainWindow {
Q_OBJECT
public:
explicit JanelaPrincipal(QWidget *parent = nullptr);
~JanelaPrincipal();
private:
Ui::JanelaPrincipal *ui_base;
// Interfaces geradas pelo Qt Designer
Ui::FormConfig *ui_config;
Ui::FormStatus *ui_status;
// Widgets containers
QWidget *containerConfig;
QWidget *containerStatus;
QWidget *janelaAtiva = nullptr;
};
#endif // JANELAPRINCIPAL_H
Impelmentação e Controle de Janelas (janelaprincipal.cpp)
O segredo para manter uma janela no topo está no método setWindowFlags utilizando o atributo Qt::WindowStaysOnTopHint. No exemplo abaixo, as janelas são configuradas como diálogos que forçam a sobreposição.
#include "janelaprincipal.h"
#include "ui_janelaprincipal.h"
#include "ui_form_config.h"
#include "ui_form_status.h"
#include <QTimer>
#include <QApplication>
#include <QDebug>
JanelaPrincipal::JanelaPrincipal(QWidget *parent) :
QMainWindow(parent),
ui_base(new Ui::JanelaPrincipal)
{
ui_base->setupUi(this);
// Inicialização dos containers e das UIs
containerConfig = new QWidget();
containerStatus = new QWidget();
ui_config = new Ui::FormConfig();
ui_status = new Ui::FormStatus();
ui_config->setupUi(containerConfig);
ui_status->setupUi(containerStatus);
// Configuração de títulos e flags de comportamento
containerConfig->setWindowTitle("Ajustes do Sistema");
containerStatus->setWindowTitle("Monitoramento");
// Define a janela para ficar sempre visível sobre as outras
containerConfig->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
containerStatus->setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
// Lógica para abrir a janela de configuração
connect(ui_base->btnAbrirConfig, &QPushButton::clicked, this, [=]() {
if(janelaAtiva) janelaAtiva->hide();
containerConfig->show();
janelaAtiva = containerConfig;
// Desabilita a janela principal para simular um comportamento modal customizado
this->setEnabled(false);
});
// Retorno ao fechar ou cancelar nos widgets secundários
auto fecharSubjanela = [=]() {
this->setEnabled(true);
if(janelaAtiva) {
janelaAtiva->hide();
janelaAtiva = nullptr;
}
};
connect(ui_config->btnSalvar, &QPushButton::clicked, this, fecharSubjanela);
connect(ui_config->btnCancelar, &QPushButton::clicked, this, fecharSubjanela);
// Monitoramento de foco com Timer para feedback visual
QTimer* monitorFoco = new QTimer(this);
connect(monitorFoco, &QTimer::timeout, this, [=]() {
QWidget *focoAtual = QApplication::activeWindow();
if (janelaAtiva) {
if (focoAtual == janelaAtiva) {
// Remove destaque se a janela estiver com foco
janelaAtiva->setStyleSheet("");
} else {
// Aplica uma borda vermelha se o usuário clicar fora da janela ativa
janelaAtiva->setStyleSheet("border: 2px solid red;");
}
}
});
monitorFoco->start(200);
}
JanelaPrincipal::~JanelaPrincipal() {
delete ui_base;
delete containerConfig;
delete containerStatus;
delete ui_config;
delete ui_status;
}
Diferenças de Modalidade
Ao lidar com janelas no Qt, existem duas abordagens principais para gerenciar o foco:
- Qt::ApplicationModal: Bloqueia a interação com todas as outras janelas da aplicação automaticamente. É a forma mais simples de criar um diálogo, mas oferece menos controle sobre animações ou estados intermediários da janela principal.
- setWindowFlags com setEnabled: Ao desabilitar manualmente a janela principal (
this->setEnabled(false)) e usar a flagWindowStaysOnTopHint, o desenvolvedor ganha flexibilidade. Isso permite, por exemplo, manter processos de background visíveis ou aplicar estilos de CSS (como a borda de alerta no exemplo do timer) quando a atenção do usuário é desviada.
O uso do QApplication::activeWindow() combinado com um QTimer é uma técnica útil para validação em tempo real de interfaces que exigem resopsta imediata do operador, garantindo que janelas críticas não sejam ignoradas atrás de outros elementos da interface.