QGraphicsView使用鼠标滚轮在鼠标位置放大和缩小 [英] QGraphicsView Zooming in and out under mouse position using mouse wheel

查看:4304
本文介绍了QGraphicsView使用鼠标滚轮在鼠标位置放大和缩小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序在屏幕中间有一个 QGraphicsView 窗口。我想使用鼠标滚轮放大和缩小。



目前我已重新实现 QGraphicsView 并覆盖鼠标滚动功能,使其不滚动图像(像它默认情况下)。

  void MyQGraphicsView :: wheelEvent(QWheelEvent * event)
{
if(event-> delta ()> 0)
{
emit mouseWheelZoom(true);
}
else
{
emit mouseWheelZoom(false);
}
}

所以当我滚动时,



然后,我将此信号连接到插槽(缩放功能见下文)类处理我的GUI东西。现在基本上我认为我的缩放功能只是不是最好的方式做它在所有我见过一些人使用overriden wheelevent函数来设置规模,但我不能真正找到一个完整的答案。



所以我做了这个,但它不是完美的任何方式,所以我正在寻找这个调整一点或一个工作示例使用滚动事件函数中的缩放。 p>

我在构造函数中初始化 m_zoom_level 0 p>

  void Display :: zoomfunction(bool zoom)
{
QMatrix matrix;

if(zoom& m_zoom_level< 500)
{
m_zoom_level = m_zoom_level + 10;
ui-> graphicsView-> setTransformationAnchor(QGraphicsView :: AnchorUnderMouse);
matrix.scale(m_zoom_level,m_zoom_level);

ui-> graphicsView-> setMatrix(matrix);
ui-> graphicsView-> scale(1,-1);
}
else if(!zoom)
{
m_zoom_level = m_zoom_level - 10;
ui-> graphicsView-> setTransformationAnchor(QGraphicsView :: AnchorUnderMouse);
matrix.scale(m_zoom_level,m_zoom_level);

ui-> graphicsView-> setMatrix(matrix);
ui-> graphicsView-> scale(1,-1);
}
}

正如你可以看到, code> QMatrix 和缩放,并将其设置到Graphicsview和设置转换锚到鼠标下,但它只是不能正常工作,有时如果我滚动加载它将开始放大只有(我认为是用int循环或某事)。



正如我所说的帮助这个或一个很好的例子,在鼠标下的规模将是巨大的。

解决方案

这种缩放有点棘手。让我分享我自己的课程。



标题:

  #include< QObject> 
#include< QGraphicsView>

/ *!
*此类添加了使用鼠标滚轮缩放QGraphicsView的能力。光标
*下的点保持不动,尽管可能。
*
*请注意,当场景的
*大小与视口大小相比不够大时,就不可能了。 QGraphicsView中心的图片
*,当它小于视图。和QGraphicsView的滚动边界不允许
*放任何图片点在任何视口位置。
*
*当用户开始滚动时,该类记住原始场景位置,
*保持滚动,直到滚动完成。它比在每个滚动步骤获得原始场景位置
*更好,因为这种方法导致位置错误,由于前面提到的
*定位限制。
*
*当使用scroll滚动时,此类发出zoomed()信号。
*
*用法:
*
* new Graphics_view_zoom(view);
*
*删除视图时,对象将被自动删除。
*
*您可以使用set_modified()设置用于缩放的键盘修饰符。缩放将
*仅在修改器组合的完全匹配时执行。默认修饰符为Ctrl。
*
*您可以通过调用set_zoom_factor_base()来更改缩放速度。
*缩放系数计算为zoom_factor_base ^ angle_delta
*(请参阅QWheelEvent :: angleDelta)。
*默认缩放系数基数为1.0015。
* /
class Graphics_view_zoom:public QObject {
Q_OBJECT
public:
Graphics_view_zoom(QGraphicsView * view);
void gentle_zoom(double factor);
void set_modifiers(Qt :: KeyboardModifiers modifiers);
void set_zoom_factor_base(double value);

private:
QGraphicsView * _view;
Qt :: KeyboardModifiers _modifiers;
double _zoom_factor_base;
QPointF target_scene_pos,target_viewport_pos;
bool eventFilter(QObject * object,QEvent * event);

信号:
void zoomed();
};

资料来源:

 code> #includeGraphics_view_zoom.h
#include< QMouseEvent>
#include< QApplication>
#include< QScrollBar>
#include< qmath.h>

Graphics_view_zoom :: Graphics_view_zoom(QGraphicsView * view)
:QObject(view),_view(view)
{
_view-> viewport installEventFilter(this);
_view-> setMouseTracking(true);
_modifiers = Qt :: ControlModifier;
_zoom_factor_base = 1.0015;
}

void Graphics_view_zoom :: gentle_zoom(double factor){
_view-> scale(factor,factor);
_view-> centerOn(target_scene_pos);
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view-> viewport() - > width()/ 2.0,
_view-> viewport() - > height()/ 2.0);
QPointF viewport_center = _view-> mapFromScene(target_scene_pos) - delta_viewport_pos;
_view-> centerOn(_view-> mapToScene(viewport_center.toPoint()));
emit zoomed();
}

void Graphics_view_zoom :: set_modifiers(Qt :: KeyboardModifiers modifiers){
_modifiers = modifiers;

}

void Graphics_view_zoom :: set_zoom_factor_base(double value){
_zoom_factor_base = value;
}

bool Graphics_view_zoom :: eventFilter(QObject * object,QEvent * event){
if(event-> type()== QEvent :: MouseMove){
QMouseEvent * mouse_event = static_cast< QMouseEvent *>(event);
QPointF delta = target_viewport_pos - mouse_event-> pos();
if(qAbs(delta.x())> 5 || qAbs(delta.y())> 5){
target_viewport_pos = mouse_event-> pos
target_scene_pos = _view-> mapToScene(mouse_event-> pos());
}
} else if(event-> type()== QEvent :: Wheel){
QWheelEvent * wheel_event = static_cast< QWheelEvent *>(event);
if(QApplication :: keyboardModifiers()== _modifiers){
if(wheel_event-> orientation()== Qt :: Vertical){
double angle = wheel_event-> angleDelta ().y();
double factor = qPow(_zoom_factor_base,angle);
gentle_zoom(factor);
return true;
}
}
}
Q_UNUSED(object)
return false;
}

使用示例:

  Graphics_view_zoom * z = new Graphics_view_zoom(ui-> graphicsView); 
z-> set_modifiers(Qt :: NoModifier);


I have an application with a QGraphicsView window in the middle of the screen. I want to be able to zoom in and out using a mouse wheel scroll.

Currently I have re-implemented QGraphicsView and overriden the mouse scroll function so that it doesn't scroll the image (like it does by default).

void MyQGraphicsView::wheelEvent(QWheelEvent *event)
{
    if(event->delta() > 0)
    {
        emit mouseWheelZoom(true);
    }
    else
    {
        emit mouseWheelZoom(false);
    }
}

so when I scroll, I'm emitting a signal true if mouse wheel forward false if mouse wheel back.

I have then connected this signal to a slot (zoom function see below) in the class that handles my GUI stuff. Now basically I think my zoom function just isn't the best way to do it at all I have seen some examples of people using the overriden wheelevent function to set scales but I couldn't really find a complete answer.

So instead I have done this but it's not perfect by any means so I'm looking for this to be tweaked a bit or for a working example using scale in the wheel event function.

I initialize m_zoom_level to 0 in the constructor.

void Display::zoomfunction(bool zoom)
{
    QMatrix matrix;

    if(zoom && m_zoom_level < 500)
    {
        m_zoom_level = m_zoom_level + 10;
        ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
        matrix.scale(m_zoom_level, m_zoom_level);

        ui->graphicsView->setMatrix(matrix);
        ui->graphicsView->scale(1,-1);
    }
    else if(!zoom)
    {
        m_zoom_level = m_zoom_level - 10;
        ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
        matrix.scale(m_zoom_level, m_zoom_level);

        ui->graphicsView->setMatrix(matrix);
        ui->graphicsView->scale(1,-1);
    }
}

As you can see above I'm using a QMatrix and scaling that and setting it to the Graphicsview and setting the transformation anchor to under mouse, but its just not working perfectly sometimes if I'm scrolling loads it will just start to zoom in only (which I think is to do with the int looping over or something).

As I said help with this or a good example of scale under mouse would be great.

解决方案

Such zooming is a bit tricky. Let me share my own class for doing that.

Header:

#include <QObject>
#include <QGraphicsView>

/*!
 * This class adds ability to zoom QGraphicsView using mouse wheel. The point under cursor
 * remains motionless while it's possible.
 *
 * Note that it becomes not possible when the scene's
 * size is not large enough comparing to the viewport size. QGraphicsView centers the picture
 * when it's smaller than the view. And QGraphicsView's scrolls boundaries don't allow to
 * put any picture point at any viewport position.
 *
 * When the user starts scrolling, this class remembers original scene position and
 * keeps it until scrolling is completed. It's better than getting original scene position at
 * each scrolling step because that approach leads to position errors due to before-mentioned
 * positioning restrictions.
 *
 * When zommed using scroll, this class emits zoomed() signal.
 *
 * Usage:
 *
 *   new Graphics_view_zoom(view);
 *
 * The object will be deleted automatically when the view is deleted.
 *
 * You can set keyboard modifiers used for zooming using set_modified(). Zooming will be
 * performed only on exact match of modifiers combination. The default modifier is Ctrl.
 *
 * You can change zoom velocity by calling set_zoom_factor_base().
 * Zoom coefficient is calculated as zoom_factor_base^angle_delta
 * (see QWheelEvent::angleDelta).
 * The default zoom factor base is 1.0015.
 */
class Graphics_view_zoom : public QObject {
  Q_OBJECT
public:
  Graphics_view_zoom(QGraphicsView* view);
  void gentle_zoom(double factor);
  void set_modifiers(Qt::KeyboardModifiers modifiers);
  void set_zoom_factor_base(double value);

private:
  QGraphicsView* _view;
  Qt::KeyboardModifiers _modifiers;
  double _zoom_factor_base;
  QPointF target_scene_pos, target_viewport_pos;
  bool eventFilter(QObject* object, QEvent* event);

signals:
  void zoomed();
};

Source:

#include "Graphics_view_zoom.h"
#include <QMouseEvent>
#include <QApplication>
#include <QScrollBar>
#include <qmath.h>

Graphics_view_zoom::Graphics_view_zoom(QGraphicsView* view)
  : QObject(view), _view(view)
{
  _view->viewport()->installEventFilter(this);
  _view->setMouseTracking(true);
  _modifiers = Qt::ControlModifier;
  _zoom_factor_base = 1.0015;
}

void Graphics_view_zoom::gentle_zoom(double factor) {
  _view->scale(factor, factor);
  _view->centerOn(target_scene_pos);
  QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
                                                             _view->viewport()->height() / 2.0);
  QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
  _view->centerOn(_view->mapToScene(viewport_center.toPoint()));
  emit zoomed();
}

void Graphics_view_zoom::set_modifiers(Qt::KeyboardModifiers modifiers) {
  _modifiers = modifiers;

}

void Graphics_view_zoom::set_zoom_factor_base(double value) {
  _zoom_factor_base = value;
}

bool Graphics_view_zoom::eventFilter(QObject *object, QEvent *event) {
  if (event->type() == QEvent::MouseMove) {
    QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
    QPointF delta = target_viewport_pos - mouse_event->pos();
    if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
      target_viewport_pos = mouse_event->pos();
      target_scene_pos = _view->mapToScene(mouse_event->pos());
    }
  } else if (event->type() == QEvent::Wheel) {
    QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
    if (QApplication::keyboardModifiers() == _modifiers) {
      if (wheel_event->orientation() == Qt::Vertical) {
        double angle = wheel_event->angleDelta().y();
        double factor = qPow(_zoom_factor_base, angle);
        gentle_zoom(factor);
        return true;
      }
    }
  }
  Q_UNUSED(object)
  return false;
}

Usage example:

Graphics_view_zoom* z = new Graphics_view_zoom(ui->graphicsView);
z->set_modifiers(Qt::NoModifier);

这篇关于QGraphicsView使用鼠标滚轮在鼠标位置放大和缩小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆