2016-02-12 137 views
0

我有一個窗口,其中是一個QGraphicsView,它將顯示圖像。我已經實現了wheelEvent()。我的圖像大多比窗口大,所以我在窗口中看到滾動條。Qt 5:縮放圖像的鼠標滾輪事件行爲

當我們轉動車輪,同時查看Windows照片查看器中的圖像是,當我們移動輪向上(向它的線),在圖像放大和我們通常觀察到時,我們將其移動(朝排出體外) ,圖像縮小。

我得到的是當我向自己移動輪子(縮小圖像)而不是縮小圖像時,首先向下滾動,並且只有當滾動條接觸其最底部點時纔開始縮小。

通過嘗試代碼來理解問題會更好。我猜我無法解釋。

我想要標準的行爲。該怎麼辦?

代碼

#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)); 

} 

EDIT

1)刪除功能void viewer::wheelEvent(QWheelEvent * event)viewer.cpp

2)將bool viewer::eventFilter(QObject *obj, QEvent *event)在其位置作爲受保護的功能和void viewer::handleWheelOnGraphicsScene(QGraphicsSceneWheelEvent* scrollevent)作爲一種公開槽viewer.h

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)); 

} 
+0

傳播我的意思是事件在一個鏈中處理。當事件發送到一個不處理它的小部件(例如按鈕上的滾輪事件)時,它將被傳播到它的父小部件,以便它能夠處理它(例如包含該按鈕的滾動視圖)。這同樣適用於事件過濾器。 –

回答

2

該代碼顯示您沒有子類QGraphicsView,而是在您自己的小部件中使用一個。

車輪事件將首先發送到實際的圖形視圖控件。在那裏用Qt的默認行爲處理,即滾動。只有滾動到底部時,圖形視圖才能處理輪子事件,並將其傳播到其父級,即班級。這就是爲什麼只有在滾動到邊框時才能縮放。

要解決此問題,您應該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; 
} 

更新
我只是想出了該事件過濾器將不會收到該圖形視圖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或者隨便你怎麼稱呼它,應該是一個私有方法,而不必是一個插槽。

+0

我對代碼做了一些更改。現在我的圖像根本不滾動。它只在滾動輪子時上下移動。什麼地方出了錯? – Nancy

+0

一切正常,因爲我想要的。感謝您的幫助。 – Nancy