6

我将 QGraphicsView 子类化为要在 CAD 应用程序中使用的自定义画布。我已经成功地重新实现了 QGraphicsView::wheelEvent 来检查控制键的键盘修饰符,如果按下控制键,则进行缩放。当用户按住 shift 并使用滚轮时,我正在尝试实现水平滚动。

我遇到的问题是水平滚动也总是向上滚动 0.279。不是一个大问题,但非常烦人,它指出了其他问题。

所以,这里有几个问题:

  1. 这是实现水平滚动的正确方法吗?如果不是,那是什么?
  2. 如何消除这个 0.279 的增量?

提前致谢。下面的代码和示例输出

void myView::zoom(int delta)
{
    double factor = pow(1.2, delta/abs(delta));
    this->scale(factor, factor);
}

void myView::scrollHorizontal(int level)
{
    QPointF center = mapToScene(viewport()->rect().center());
    qDebug() << "center: " << center.x() << ", " << center.y();
    centerOn(QPointF(center.x() - level, center.y()));
}

void myView::wheelEvent(QWheelEvent *event)
{
    //qDebug() << "delta: " << event->delta();
    if (event->modifiers() & Qt::ControlModifier)
    {
        this->zoom(event->delta());
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        this->scrollHorizontal(event->delta());
    }
    else
        QGraphicsView::wheelEvent(event);
}

位于场景左边缘时,scrollHorizo​​ntal 中 qDebug() 行的示例输出:

center:  261.5 ,  615.654 
center:  261.5 ,  615.375 
center:  261.5 ,  615.096 
center:  261.5 ,  614.817 
center:  261.5 ,  614.538 
center:  261.5 ,  614.259 
center:  261.5 ,  613.98 
center:  261.5 ,  613.701 
center:  261.5 ,  613.421 
4

1 回答 1

5

您的问题来自mapToScene()处理整数点而不是浮点的事实。对于特定视口大小,舍入误差始终以相同的方式指向,因此您总是添加一些增量。

您想直接修改滚动条的value属性或将事件发送到水平滚动条。我已经实现了后者,它很简单。

在 Mac 上,您必须绝对禁用应用程序的滚动条惯性。否则,一旦您松开修改器并将手指从触控板/滚轮上抬起,由于惯性,垂直滚动将继续。这会让 Mac 用户的体验很糟糕,他们会因此而讨厌你 :)

截屏

gview-scroll.pro

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = gview-scroll
TEMPLATE = app
macx {
    LIBS += -framework Foundation
    OBJECTIVE_SOURCES += helper.m
}
SOURCES += main.cpp

helper.m

//helper.m
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSString.h>

void disableMomentumScroll(void)
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"AppleMomentumScrollSupported"];
    [defaults registerDefaults:appDefaults];
}

main.cpp

//main.cpp
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtCore/qmath.h>
#include <QScrollBar>
#include <QWheelEvent>
#include <QDebug>

class View : public QGraphicsView {
public:
    void zoom(int delta) {
        double factor = qPow(1.2, delta/qAbs(delta));
        scale(factor, factor);
    }
    void wheelEvent(QWheelEvent *event) {
        if (event->modifiers() & Qt::ControlModifier) {
            zoom(event->delta());
        }
        else if (event->modifiers() & Qt::ShiftModifier) {
            horizontalScrollBar()->event(event);
        }
        else {
            QGraphicsView::wheelEvent(event);
        }
    }
public:
    explicit View(QWidget *parent=0) : QGraphicsView(parent) {}
    explicit View(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene, parent) {}
};

#ifndef Q_OS_MAC
void disableMomentumScroll() {}
#else
extern "C" { void disableMomentumScroll(); }
#endif

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    disableMomentumScroll();
    QGraphicsScene s;
    s.addEllipse(-50, -50, 100, 100, QPen(Qt::red), QBrush(Qt::gray));
    View w(&s);
    w.show();
    return a.exec();
}
于 2013-08-26T21:21:14.477 回答