quinta-feira, 12 de março de 2015

ScrollArea e Qt: uma briga contante

O Qt tem muita coisa bacana, e a documentação é bem completa e útil. Mas as vezes é bem difícil descobrir como se faz algo "simples". Dessa vez eu estava tentando capturar o evento de rolagem do mouse (a "rodinha" ou mouse wheel) para permitir ao usuário efetuar zoom na imagem em exibição. A organização visual é de fato simples: eu tenho um componente (widget) customizado que contém uma QScrollArea e dentro dela uma QLabel com a imagem.

O problema é que o QScrollArea já captura e trata esse evento do mouse: ele usa pra rolar tanto vertical (a rodinha do mouse usada sozinha) como horizontalmente (a rodinha do mouse usada quando a tecla Alt está pressionada) quando a imagem é maior do que a área de visualização. E então, ele simplesmente não repassa o evento para que ele possa ser capturado pelo componente externo. Também não há nenhum sinal que possa ser conectado a um método para fazer isso.

Afortunadamente, eu encontrei essa postagem muito bacana que sugere o uso de filtros de evento para fazer justamente isso: fazer com que o QScrollArea simplesmente não receba o evento, que assim não vai ser tratado e continuará a ser encaminhado até o componente mais externo. Bom, eu não queria ter que reimplementar todo o tratamento de rolagem já muito bem realizado pelo QScrollArea, então eu usei o método QApplication::keyboardModifiers() para ignorar o evento apenas quando a tecla Ctrl estiver pressionada (pois ai sim eu aplicarei o zoom intencionado).

Eis o exemplo de código:

// +-----------------------------------------------------------
ChildWindow::ChildWindow(QWidget* pParent) :
    QWidget(pParent)
{
. . .
// Make the scroll ignore the mouse wheel events
// (they will be handled at this class scope). 
m_pScrollArea->viewport()->installEventFilter(this);
. . .
}

// +-----------------------------------------------------------
bool ChildWindow::eventFilter(QObject *pObject, QEvent *pEvent)
{
// Ignore the mouse wheel events if the Ctrl key is pressed
bool bCtrl = QApplication::keyboardModifiers() &
Qt::ControlModifier;
if(pEvent->type() == QEvent::Wheel && bCtrl)
{
pEvent->ignore();
return true;
}
return false;
}

// +-----------------------------------------------------------
void f3::ChildWindow::wheelEvent(QWheelEvent *pEvent)
{
QPoint oPixels = pEvent->pixelDelta();
  QPoint oDegrees = pEvent->angleDelta() / 8;
QPoint oSteps = oDegrees / 15;

QPoint oDelta = !oPixels.isNull() ? oPixels : oDegrees;

// Scale the image based on the wheel delta
scaleImageBy(oDelta);

pEvent->accept();
}

Nenhum comentário:

Postar um comentário