Qt 5 : Mouse Wheel event behaviour for zooming image

标签 qt qt5 mousewheel

我有一个窗口,其中有一个 QGraphicsView,它将显示图像。我已经实现了wheelEvent()。我的图像大多比窗口大,所以我在窗口中看到滚动条。

当我们在 Windows 照片查看器中查看图像时旋转滚轮时,我们通常会观察到,当我们向上移动滚轮(朝向其电线)时,图像会放大,而当我们向下移动滚轮(朝向 body 外侧)时,图像缩小。

我得到的是,当我将滚轮移向自己(缩小)图像而不是缩小时,首先向下滚动,并且仅当滚动条触及其最底部点时才开始缩小。

通过尝试代码会更好地理解问题。我猜我无法解释。

我想要标准行为。该怎么办?

代码

#include "viewer.h"
#include "ui_viewer.h"
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsPixmapItem>
#include <QWheelEvent>
#include <QDebug>
#include <QImage>
#include <QImageReader>
#include <QApplication>
#include <QDesktopWidget>

viewer::viewer(QWidget *parent) : QWidget(parent),ui2(new Ui::viewer)
{
     ui2->setupUi(this);
} 

viewer::~viewer()
{
    delete ui2;
}

int viewer::show_changes(QString folder)
{
    QDesktopWidget *desktop = QApplication::desktop();
    int screenWidth  = desktop->width();
    int screenHeight = desktop->height();
    QString filename = "image_bigger_than_window.jpg";
    QPixmap pixmap = QPixmap(filename);
    QImageReader reader(filename);
    QImage image = reader.read();
    QSize size = image.size();
    int width = 800;
    int height = (width * size.height()) / size.width();
    int x = (screenWidth - width) / 2;
    int y = (screenHeight - height) / 2 - 30;
    setGeometry(x,y,width, height);
    setWindowTitle("OUTPUT");
    ui2->graphicsView->setGeometry(0,0,width,height);
    QGraphicsScene* viewScene = new QGraphicsScene(QRectF(0, 0,width,  height), 0);
    QGraphicsPixmapItem *item = viewScene->addPixmap(pixmap.scaled(QSize((int)viewScene->width(), (int)viewScene->height()),
                             Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    viewScene->addItem(item);
    ui2->graphicsView->fitInView(QRectF(0, 0, width,     height),Qt::IgnoreAspectRatio);
    ui2->graphicsView->setScene(viewScene);
    ui2->graphicsView->show();
    return 0;
}

void viewer::wheelEvent(QWheelEvent * event)
{
    const int degrees = event->delta() / 8;
    qDebug() << degrees;
    int steps = degrees / 15;        
    double scaleFactor = 1.0; 
    const qreal minFactor = 1.0;
    const qreal maxFactor = 10.0;
    qreal h11 = 1.0, h22 = 0;
    if(steps > 0)
    {
        h11 = (h11 >= maxFactor) ? h11 : (h11 + scaleFactor);
        h22 = (h22 >= maxFactor) ? h22 : (h22 + scaleFactor);
    }
    else
    {
        h11 = (h11 <= minFactor) ? minFactor : (h11 - scaleFactor);
        h22 = (h22 <= minFactor) ? minFactor : (h22 - scaleFactor);
    }
    ui2->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    ui2->graphicsView->setTransform(QTransform(h11, 0, 0,0, h22, 0, 0,0,1));

}

编辑

1)从 viewer.cpp 中删除了函数 voidviewer::wheelEvent(QWheelEvent * event)

2)将 boolviewer::eventFilter(QObject *obj, QEvent *event) 放在其位置作为 protected 函数,并将 voidviewer::handleWheelOnGraphicsScene(QGraphicsSceneWheelEvent*scrollevent) code> 作为 viewer.h

中的公共(public)槽
bool viewer::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::GraphicsSceneWheel)
    {    
        QGraphicsSceneWheelEvent *scrollevent = static_cast<QGraphicsSceneWheelEvent *>(event);
        handleWheelOnGraphicsScene(scrollevent);
        return true;
    }
  // Other events should propagate - what do you mean by propagate here?
  return false;
}

 void viewer::handleWheelOnGraphicsScene(QGraphicsSceneWheelEvent* scrollevent)
{
   const int degrees = scrollevent->delta()  / 8;
   qDebug() << degrees;
   int steps = degrees / 15;
   qDebug() << steps;
   double scaleFactor = 1.0; //How fast we zoom
   const qreal minFactor = 1.0;
   const qreal maxFactor = 10.0;
   if(steps > 0)
   {
      h11 = (h11 >= maxFactor) ? h11 : (h11 + scaleFactor);
      h22 = (h22 >= maxFactor) ? h22 : (h22 + scaleFactor);
   }
   else
  {
      h11 = (h11 <= minFactor) ? minFactor : (h11 - scaleFactor);
      h22 = (h22 <= minFactor) ? minFactor : (h22 - scaleFactor);
  } 
ui2->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ui2->graphicsView->setTransform(QTransform(h11, 0, 0,0, h22, 0, 0,0,1));

}

最佳答案

代码显示您没有子类化QGraphicsView,而是在您自己的小部件中使用一个子类。

滚轮事件将首先发送到实际的图形 View 小部件。在那里它是用 Qt 的默认行为来处理的,即滚动。仅当您滚动到底部时,图形 View 才无法处理滚轮事件,并且它会传播到其父级(即您的类)。这就是为什么只有滚动到边框时才能缩放。

要解决此问题,您应该 install an event filter 。这允许您拦截滚轮事件并在您的类中处理它:

// Outline, not tested
viewer::viewer(QWidget *parent) : QWidget(parent),ui2(new Ui::viewer)
{
    ui2->setupUi(this);
    // Let me handle your events
    ui2->graphicsView->installEventFilter(this);
} 

// should be protected
bool viewer::eventFilter(QObject *obj, QEvent *event) {
  if (event->type() == QEvent::GraphicsSceneWheel) {
      // Your implementation. 
      // You can't use QWheelEvent, as Graphicscene works with its own events...
     handleWheelOnGraphicsScene(static_cast<QGraphicsSceneWheelEvent*> (event));

     // Don't propagate
     return true;
  }

  // Other events should propagate
  return false;
}

更新
我刚刚发现事件过滤器不会接收图形 View 上的 GraphicsSceneWheel 事件。相反,您必须在图形场景上安装过滤器。另外,您必须调用event->accept(),这样它就不会传播。

更新后的代码:

// In Constructor, or where appropriate
ui2->graphicsView->scene()->installEventFilter(this);


bool viewer::eventFilter(QObject *obj, QEvent *event) {
    if (event->type() == QEvent::GraphicsSceneWheel) {
        handleWheelOnGraphicsScene(static_cast<QGraphicsSceneWheelEvent*> (event));

        // Don't propagate
        event->accept();
        return true;
    }
    return false;
}

另请注意,handleWheelOnGraphicsScene 或任何您想调用的名称都应该是私有(private)方法,并且不必是插槽。

关于Qt 5 : Mouse Wheel event behaviour for zooming image,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35364401/

相关文章:

C++ 错误 : "use of deleted function" with minGW_32, Qt 5.7.0,windows 10

c# - 如何为User32.dll的sendInput方法在mouse_input中设置适当的缩放值?

c++ - 向 QString 中的每一行添加字符

c++ - 如何在没有 ImageMagick 的情况下将 ImageMagick 图像导入 Qt5 应用程序?

qt - 配方 linkandpoSTLink 失败,退出代码 1 错误

c++ - 当指定文件的路径包含空格时如何用QProcess启动explorer.exe?

javascript - 在Cesium中禁用鼠标滚轮

google-chrome - Chrome - Javascript 阻止默认的 Ctrl + MouseWheel 行为

c++ - QML TableView + QAbstractTableModel - 如何从 QML 编辑模型数据?

c++ - 2个套接字之间无法通信