PDA

View Full Version : QPrintPreviewWidget mouse wheel events



ChrisW67
24th October 2013, 03:47
G'day all,

Perhaps I am suffering brain fade or caffeine withdrawal but I am sure someone can help.

I have a QPrintPreviewWidget displaying a multi-page document. The mouse wheel scrolls up and down through the pages quite happily. I'd like to trap mouse wheel events when the Control key is pressed to zoom in and out.

My first approach was to subclass QPrintPreviewWidget and override wheelEvent(). Unfortunately the new wheelEvent() does not get called unless the preview scroll area has moved all the way to the top (bottom) of the document. The vertical scroll bar is consuming the event before I can see it, and stop consuming it if it can no longer scroll. The result is the Ctrl-Wheel only zooms at top or bottom of the document.

My second approach was to install an event filter hoping to see the wheel events before the scroll bars consumed them. This suffers the same problem.

Both approaches shown below. Similar result Qt4.8.4 and 5.1.0 on Linux.

How do I get these events before the scroll area/bars?

Cheers,
Chris



#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QPrinter>
#include <QPrintPreviewWidget>
#include <QVBoxLayout>
#include <QWheelEvent>
#include <QWidget>
#include <cmath>

class PreviewWidget: public QPrintPreviewWidget {
Q_OBJECT
public:
PreviewWidget(QWidget *parent = 0): QPrintPreviewWidget(parent) { }

protected:
void wheelEvent(QWheelEvent *event) {
if (event->orientation() == Qt::Vertical && (event->modifiers() & Qt::ControlModifier)) {
double numDegrees = event->delta() / 8.0;
double numSteps = numDegrees / 15.0;
double factor = std::pow(1.125, numSteps);
zoomIn(factor);
event->accept();
}
event->ignore();
}
};

class Widget : public QWidget {
Q_OBJECT

public:
explicit Widget(QWidget *parent = 0): QWidget(parent) {
m_printPreview = new PreviewWidget(this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_printPreview);
connect(m_printPreview, SIGNAL(paintRequested(QPrinter*)), SLOT(paintRequested(QPrinter*)));
setLayout(layout);
resize(400, 800);
// m_printPreview->installEventFilter(this);
}

public slots:
void paintRequested(QPrinter *printer) {
QPainter p(printer);
QFont big("Arial", 200);
p.setFont(big);
for (int i = 0; i < 4; ++i) {
p.drawText(300, 200, QString::number(i));
printer->newPage();
}
}

protected:
bool eventFilter(QObject *obj, QEvent *event) {
if (obj == m_printPreview && event->type() == QEvent::Wheel) {
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
if (wheelEvent->orientation() == Qt::Vertical && (wheelEvent->modifiers() & Qt::ControlModifier)) {
double numDegrees = wheelEvent->delta() / 8.0;
double numSteps = numDegrees / 15.0;
double factor = std::pow(1.125, numSteps);
m_printPreview->zoomIn(factor);
// wheelEvent->accept();
return true;
}
// wheelEvent->ignore();
return false;
}
else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}

private:
PreviewWidget *m_printPreview;
};


int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"

stampede
24th October 2013, 07:15
You can always install event filter on qApp and filter the event out only if m_printPreview is underMouse().

ChrisW67
24th October 2013, 10:22
It's a bit like using a sledgehammer to crack a walnut though :)

ChrisW67
26th October 2013, 07:32
Looks like it is the sledgehammer approach or nothing. The scroll bars belong to a private QGraphicsView and the events are not routed via QPrintPreviewWidget in any way I can see.

On the plus side, I solved another problem by "accident" while looking at this one. :D