由于项目要求,需要在QWidget中实现一个手势操作的功能,对图片进行放大/缩小/平移功能,并且还需要支持通过鼠标和键盘来实现该功能。其实这种功能在QGraphicsView中实现比较简单, 不过在QWidget中也能实现,本次通过QGestureEvent来捕捉手势操作,然后对图片进行缩放或者移动。
废话不多说,直接上代码
首先来看头文件:
class QGestureEvent;
class QPanGesture;
class QPinchGesture;
class QSwipeGesture;
class CProjectionPicture;
class CProjectionPicture : public QWidget
{
Q_OBJECT
public:
CProjectionPicture(QWidget *parent = 0);
void setPicture(QImage & image);
protected:
// 放大/缩小
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
// 平移
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
bool event(QEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
public Q_SLOTS:
void zoomIn(); // 放大
void zoomOut(); // 缩小
void zoom(float scale); // 缩放 - scaleFactor:缩放的比例因子
void translate(QPointF delta); // 平移
private:
bool gestureEvent(QGestureEvent *event);
void panTriggered(QPanGesture*);
void pinchTriggered(QPinchGesture*);
QImage loadImage(const QString &fileName);
QImage currentImage;
qreal horizontalOffset;
qreal verticalOffset;
qreal scaleFactor;
qreal currentStepScaleFactor;
Qt::MouseButton m_translateButton; // 平移按钮
bool m_bMouseTranslate;
qreal m_zoomDelta; // 缩放的增量
QPoint m_lastMousePos; // 鼠标最后按下的位置
};
源文件:
CProjectionPicture::CProjectionPicture(QWidget *parent)
: QWidget(parent),
horizontalOffset(0),
verticalOffset(0),
scaleFactor(1),
currentStepScaleFactor(1),
m_translateButton(Qt::LeftButton),
m_bMouseTranslate(false),
m_zoomDelta(0.2),
{
this->setFocusPolicy(Qt::ClickFocus);
grabGesture(Qt::PanGesture);
grabGesture(Qt::PinchGesture);
grabGesture(Qt::SwipeGesture);
}
void CProjectionPicture::setPicture(QImage &image)
{
currentImage = image.convertToFormat(QImage::Format_RGB888);
update();
}
bool CProjectionPicture::event(QEvent *event)
{
if (event->type() == QEvent::Gesture)
return gestureEvent(static_cast<QGestureEvent*>(event));
return QWidget::event(event);
}
void CProjectionPicture::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QImage image = currentImage;
if(!image.isNull()){
image = image.scaled(this->width()*currentStepScaleFactor * scaleFactor,
this->height()*currentStepScaleFactor * scaleFactor,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
const qreal iw = image.width();
const qreal ih = image.height();
const qreal wh = height();
const qreal ww = width();
painter.translate(ww/2, wh/2);
painter.translate(horizontalOffset, verticalOffset);
//painter.scale(currentStepScaleFactor * scaleFactor, currentStepScaleFactor * scaleFactor);
painter.translate(-iw/2, -ih/2);
painter.drawImage(0,0,image);
}
void CProjectionPicture::mouseDoubleClickEvent(QMouseEvent *)
{
scaleFactor = 1;
currentStepScaleFactor = 1;
verticalOffset = 0;
horizontalOffset = 0;
update();
}
bool CProjectionPicture::gestureEvent(QGestureEvent *event)
{
if (QGesture *pan = event->gesture(Qt::PanGesture))
panTriggered(static_cast<QPanGesture *>(pan));
if (QGesture *pinch = event->gesture(Qt::PinchGesture))
pinchTriggered(static_cast<QPinchGesture *>(pinch));
return true;
}
void CProjectionPicture::panTriggered(QPanGesture *gesture)
{
#ifndef QT_NO_CURSOR
switch (gesture->state()) {
case Qt::GestureStarted:
case Qt::GestureUpdated:
setCursor(Qt::SizeAllCursor);
break;
default:
setCursor(Qt::ArrowCursor);
}
#endif
QPointF delta = gesture->delta();
horizontalOffset += delta.x();
verticalOffset += delta.y();
update();
}
void CProjectionPicture::pinchTriggered(QPinchGesture *gesture)
{
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
currentStepScaleFactor = gesture->totalScaleFactor();
}
if (gesture->state() == Qt::GestureFinished) {
scaleFactor *= currentStepScaleFactor;
currentStepScaleFactor = 1;
}
update();
}
void CProjectionPicture::resizeEvent(QResizeEvent*e)
{
update();
QWidget::resizeEvent(e);
}
// 上/下/左/右键向各个方向移动、加/减键进行缩放
void CProjectionPicture::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
qDebug() << event->key();
case Qt::Key_Up:
translate(QPointF(0, -5)); // 上移
break;
case Qt::Key_Down:
translate(QPointF(0, 5)); // 下移
break;
case Qt::Key_Left:
translate(QPointF(-5, 0)); // 左移
break;
case Qt::Key_Right:
translate(QPointF(5, 0)); // 右移
break;
case Qt::Key_Plus: // 放大
zoomIn();
break;
case Qt::Key_Minus: // 缩小
zoomOut();
break;
default:
QWidget::keyPressEvent(event);
}
QWidget::keyPressEvent(event);
}
// 平移
void CProjectionPicture::mouseMoveEvent(QMouseEvent *event)
{
if (m_bMouseTranslate){
QPointF mouseDelta = event->pos() - m_lastMousePos;
translate(mouseDelta);
}
m_lastMousePos = event->pos();
QWidget::mouseMoveEvent(event);
}
void CProjectionPicture::mousePressEvent(QMouseEvent *event)
{
qDebug() << "CProjectionPicture::mousePressEvent";
if (event->button() == m_translateButton) {
m_bMouseTranslate = true;
m_lastMousePos = event->pos();
setCursor(Qt::OpenHandCursor);
}
QWidget::mousePressEvent(event);
}
void CProjectionPicture::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == m_translateButton)
{
m_bMouseTranslate = false;
setCursor(Qt::ArrowCursor);
}
QWidget::mouseReleaseEvent(event);
}
// 放大/缩小
void CProjectionPicture::wheelEvent(QWheelEvent *event)
{
qDebug() << "CProjectionPicture::wheelEvent";
// QPoint numPixels = event->pixelDelta();
QPoint scrallAmount = event->angleDelta();
if(scrallAmount.y() > 0){
zoomIn();
}
else if(scrallAmount.y() < 0){
zoomOut();
}
QWidget::wheelEvent(event);
}
// 放大
void CProjectionPicture::zoomIn()
{
zoom(1 + m_zoomDelta);
}
// 缩小
void CProjectionPicture::zoomOut()
{
zoom(1 - m_zoomDelta);
}
// 缩放 - scaleFactor:缩放的比例因子
void CProjectionPicture::zoom(float scale)
{
scaleFactor *= scale;
update();
}
// 平移
void CProjectionPicture::translate(QPointF delta)
{
horizontalOffset += delta.x();
verticalOffset += delta.y();
update();
}
本文参考:http://blog.csdn.net/liang19890820/article/details/53543017