qgraphicsview 水平滚动总是有一个垂直增量

Posted

技术标签:

【中文标题】qgraphicsview 水平滚动总是有一个垂直增量【英文标题】:qgraphicsview horizontal scrolling always has a vertical delta 【发布时间】:2013-05-10 05:08:59 【问题描述】:

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

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

所以,这里有问题:

    这是实现水平滚动的正确方法吗?如果不是,是什么? 如何消除这个 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 

【问题讨论】:

这很奇怪。当您到达场景矩形的边界时,我确实发现QGraphicsView 滚动有点“不自然”,无论可见矩形在场景矩形中的哪个位置,行为是否相同? 虽然知道是什么导致了这个问题会很有趣,但从UX 的角度来看,你正在做的事情非常糟糕。如果有人想要水平滚动,他们可以简单地使用实现了它的输入设备。像所有最近的触控板、带有滚动板或多点触控的鼠标等。大概,CAD 用户可以负担得起一个不错的输入设备,而您不需要提供这样的解决方法。 【参考方案1】:

您的问题来自 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();

【讨论】:

以上是关于qgraphicsview 水平滚动总是有一个垂直增量的主要内容,如果未能解决你的问题,请参考以下文章

停止 Qt QGraphicsView 在重新调整大小时滚动

水平 UIScrollView 内部有垂直 UIScrollViews - 滚动外部水平视图时如何防止滚动内部滚动视图?

(垂直)滚动视图包含另一个(水平)滚动视图 - Kivy

如何隐藏水平滚动条并保持垂直滚动条可见,同时仍然能够水平滚动?

在水平和垂直Recyclerview中滚动问题

水平和垂直回收器视图中的滚动问题