Mecanimso de Sinais e Slots
O framework Qt utiliza o sistema de Signals (Sinais) e Slots para permitir a comunicação desacoplada entre objetos. Quando um objeto altera seu estado, ele emite um sinal. O emissor não possui conhecimento sobre quais objetos receberão essa notificação, garantindo o encapsulamento.
Os Slots são funções membros comuns que podem ser conectadas aos sinais. Um slot é executado sempre que o sinal ao qual está vinculado é disparado. A conexão é estabelecida através da função estática QObject::connect.
// Sintaxe clássica utilizando macros
bool QObject::connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type = Qt::AutoConnection);
As macros SIGNAL() e SLOT() convertem as assinaturas das funções em strings, permitindo que o sistema de Meta-Objetos (MOC) realize o mapeamento interno. Exemplo prático de conexão:
// Conectando o clique de um botão a uma função personalizada
connect(botaoEnviar, SIGNAL(clicked()), this, SLOT(processarEnvio()));
Para desfazer um vínculo, utiliza-se a função disconnect. Vale resslatar que o Qt remove automaticamente as conexões quando um objeto envolvido é destruído. Além disso, a assinatura do sinal deve ser compatível com a do slot; o slot pode ter menos parâmetros que o sinal, ignorando os excedentes, mas nunca mais.
Utilização da Classe QTimer
A classe QTimer é a solução de alto nível para gerenciar intervalos de tempo e tarefas repetitivas. Ao iniciar um timer, o sinal timeout() é emitido periodicamente.
// Criando um temporizador cíclico
QTimer *temporizador = new QTimer(this);
connect(temporizador, SIGNAL(timeout()), this, SLOT(executarTarefa()));
temporizador->start(2000); // Dispara a cada 2 segundos
Caso seja necessário disparar o evento apenas uma vez, utiliza-se a propriedade setSingleShot:
QTimer *timerUnico = new QTimer(this);
connect(timerUnico, SIGNAL(timeout()), this, SLOT(finalizarOperacao()));
timerUnico->setSingleShot(true);
timerUnico->start(5000); // Dispara apenas uma vez após 5 segundos
Medição de Tempo com QTime
Para cronometrar a execução de trechos de código ou obter o horário atual, a classe QTime é a mais indicada.
#include <QDebug>
#include <QTime>
// Medindo a performance de um algoritmo
QTime cronometro;
cronometro.start();
// ... bloco de código complexo ...
double segundosDecorridos = cronometro.elapsed() / 1000.0;
qDebug() << "Tempo de processamento:" << segundosDecorridos << "s";
Para formatar a exibição da hora atual como uma string:
QString obterHoraFormatada() {
return QTime::currentTime().toString("hh:mm:ss.zzz");
}
Interação com QMessageBox
O Qt fornece diálogos modais prontos para exibir alertas ou solicitar confirmações simples através da classe QMessageBox.
// Exibindo uma mensagem informativa
QMessageBox::information(this, "Sucesso", "A operação foi concluída.", QMessageBox::Ok);
// Exibindo um alerta de aviso
QMessageBox::warning(this, "Atenção", "Deseja descartar as alterações?",
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
Hierarquia de Janelas e Componentes
A base de toda interface visual no Qt é a classe QWidget. As três classes principais de janelas são:
- QMainWindow: Fornece uma estrutura com barra de menus, barra de status e áreas de ferramentas.
- QDialog: Base para janelas de diálogo (curta duração).
- QWidget: A classe base para todos os objetos de interface; se não tiver um pai, ela se comporta como uma janela independente.
Conversão de Dados: QString e Tipos Numéricos
Converter strings para números e vice-versa é uma tarefa comum no desenvolvimento de interfaces.
// String para Double
QString textoPreco = "1550.75";
bool sucesso;
double valor = textoPreco.toDouble(&sucesso);
if (sucesso) {
// Processamento do valor
}
// Suporte para notação científica
double cientifico = QString("2.5e-3").toDouble(); // Resultado: 0.0025
Integração com OpenCV: Manipulação da Classe Mat
Ao trabalhar com processamento de imagem dentro do Qt com OpenCV, a estrutura principal é a cv::Mat. O acesso aos elementos pode ser feito via método at ou ponteiros para maior eficiência.
// Inicializando uma matriz de zeros (64-bit float, canal único)
cv::Mat dadosMatriz = cv::Mat::zeros(5, 5, CV_64FC1);
// Acesso direto (seguro, porém mais lento)
double valorPonto = dadosMatriz.at<double>(0, 0);
// Acesso via ponteiro (mais rápido para iterações)
double* linhaZero = dadosMatriz.ptr<double>(0);
double primeiroElemento = linhaZero[0];