Using QTransform is a good way to implement translation and scaling features. The documentation that comes with it tells you everything you need to know, but here you go I will copy and paste some code snippets together (untested!) to give you a head start.
ScalableWidget.h:
#include <QtGui>
class ScalableWidget
: public QWidget{
Q_OBJECT
double screenScale;
QTransform screenTransform;
QPointF mouse;
// current mouse location in pixel coordinates QPointF mappedMouse;
// current mouse location in logical coordinates QPointF lastMouse;
// last mouse location in pixel coordinates QPointF mouseDiff;
// last mouse motion in pixel coordinates QPointF mappedMouseDiff;
// last mouse motion in logical coordinates
public:
~ScalableWidget(){};
protected:
private:
void updateMouse
(QPointF mousePos
);
void updateScreenTransform();
};
ScalableWidget.h:
#include <QtGui>
class ScalableWidget: public QWidget
{
Q_OBJECT
double screenScale;
QPointF screenOffset;
QTransform screenTransform;
QPointF mouse; // current mouse location in pixel coordinates
QPointF mappedMouse; // current mouse location in logical coordinates
QPointF lastMouse; // last mouse location in pixel coordinates
QPointF mouseDiff; // last mouse motion in pixel coordinates
QPointF mappedMouseDiff; // last mouse motion in logical coordinates
public:
ScalableWidget(QWidget* parent=0);
~ScalableWidget(){};
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void resizeEvent(QResizeEvent *event);
private:
void updateMouse(QPointF mousePos);
void updateScreenTransform();
};
To copy to clipboard, switch view to plain text mode
ScalableWidget.cpp:
#include "ScalableWidget.h"
ScalableWidget
::ScalableWidget(QWidget *parent
){
screenScale = 0.01; // 1 px is worth 0.01 value
}
void ScalableWidget
::mousePressEvent(QMouseEvent *event
) {
mouseClick = event->posF();
mouseClickTimeStamp = stopWatch.programTime();
setCursor(Qt::ClosedHandCursor);
}
void ScalableWidget
::mouseMoveEvent(QMouseEvent *event
) {
updateMouse(event->posF());
if (event->buttons() & (Qt::LeftButton | Qt::RightButton))
{
screenOffset -= mappedMouseDiff;
updateScreenTransform();
}
update();
}
void ScalableWidget
::mouseReleaseEvent(QMouseEvent *event
) {
updateMouse(event->posF());
unsetCursor();
update();
}
{
if (event->delta() > 0)
{
screenScale /= 1.2;
}
else
{
screenScale *= 1.2;
}
updateScreenTransform();
updateMouse
(QPointF(event
->pos
()));
update();
}
{
updateScreenTransform();
}
void ScalableWidget
::updateMouse(QPointF mousePos
) {
mouse = mousePos;
mappedMouse = screenTransform.inverted().map(mouse);
mouseDiff = (mouse - lastMouse);
mappedMouseDiff = mouseDiff*screenScale;
mappedMouseDiff.ry() = -mappedMouseDiff.y();
lastMouse = mouse;
}
// Updates the transformation from screen to logical coordinates.
// This should be called each time when the scaling factor or the
// screen translation changes.
void ScalableWidget::updateScreenTransform()
{
screenTransform = QTransform();
screenTransform.translate(width()/2, height()/2); // Place the origin in the center of the screen.
screenTransform.scale(1.0/screenScale, -1.0/screenScale); // Flip it upside down and scale (zoom) it.
screenTransform.translate(-screenOffset.x(), -screenOffset.y()); // Apply the offset.
mappedMouse = screenTransform.inverted().map(mouse); //Calculate the logical mouse coordinates.
}
{
// Start the widget painter.
// Apply the coordinate transformation from device coordinates ((0,0) is in the top left corner)
// to logical coordinates, where the origin of the coordinate system is in the middle
// and y grows upwards. A scaling factor converts from pixel values to logical units
// (e.g. 100 px = 1 second).
painter.setTransform(screenTransform);
// Draw anything you want here.
}
ScalableWidget.cpp:
#include "ScalableWidget.h"
ScalableWidget::ScalableWidget(QWidget *parent)
: QWidget(parent)
{
screenScale = 0.01; // 1 px is worth 0.01 value
screenOffset = QPointF(0,0);
}
void ScalableWidget::mousePressEvent(QMouseEvent *event)
{
mouseClick = event->posF();
mouseClickTimeStamp = stopWatch.programTime();
setCursor(Qt::ClosedHandCursor);
}
void ScalableWidget::mouseMoveEvent(QMouseEvent *event)
{
updateMouse(event->posF());
if (event->buttons() & (Qt::LeftButton | Qt::RightButton))
{
screenOffset -= mappedMouseDiff;
updateScreenTransform();
}
update();
}
void ScalableWidget::mouseReleaseEvent(QMouseEvent *event)
{
updateMouse(event->posF());
unsetCursor();
update();
}
void ScalableWidget::wheelEvent(QWheelEvent *event)
{
if (event->delta() > 0)
{
screenScale /= 1.2;
}
else
{
screenScale *= 1.2;
}
updateScreenTransform();
updateMouse(QPointF(event->pos()));
update();
}
void ScalableWidget::resizeEvent(QResizeEvent* event)
{
updateScreenTransform();
}
void ScalableWidget::updateMouse(QPointF mousePos)
{
mouse = mousePos;
mappedMouse = screenTransform.inverted().map(mouse);
mouseDiff = (mouse - lastMouse);
mappedMouseDiff = mouseDiff*screenScale;
mappedMouseDiff.ry() = -mappedMouseDiff.y();
lastMouse = mouse;
}
// Updates the transformation from screen to logical coordinates.
// This should be called each time when the scaling factor or the
// screen translation changes.
void ScalableWidget::updateScreenTransform()
{
screenTransform = QTransform();
screenTransform.translate(width()/2, height()/2); // Place the origin in the center of the screen.
screenTransform.scale(1.0/screenScale, -1.0/screenScale); // Flip it upside down and scale (zoom) it.
screenTransform.translate(-screenOffset.x(), -screenOffset.y()); // Apply the offset.
mappedMouse = screenTransform.inverted().map(mouse); //Calculate the logical mouse coordinates.
}
void ScalableWidget::paintEvent(QPaintEvent*)
{
// Start the widget painter.
QPainter painter(this);
// Apply the coordinate transformation from device coordinates ((0,0) is in the top left corner)
// to logical coordinates, where the origin of the coordinate system is in the middle
// and y grows upwards. A scaling factor converts from pixel values to logical units
// (e.g. 100 px = 1 second).
painter.setTransform(screenTransform);
// Draw anything you want here.
}
To copy to clipboard, switch view to plain text mode
Bookmarks