6

CAD アプリケーションで使用するカスタム キャンバスの QGraphicsView をサブクラス化しました。QGraphicsView::wheelEvent を正常に再実装して、コントロール キーのキーボード修飾子をチェックし、コントロール キーが押された場合はズームします。ユーザーがシフトを押しながらホイールを使用すると、水平スクロールを実装しようとしています。

私が抱えている問題は、水平スクロールも常に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 に答える