2013-05-10 15 views
6

CADアプリケーションで使用するカスタムキャンバスをQGraphicsViewにサブクラス化しました。 QGraphicsView :: wheelEventを再実装して、コントロールキーのキーボード修飾子を確認し、コントロールキーが押されている場合はズームするようにしました。私は、ユーザーがシフトを保持し、ホイールを使用するときに水平スクロールを実装しようとしています。qgraphicsview水平スクロールには常に垂直方向のデルタが付きます

私が問題になっているのは、水平スクロールもです。常にが0.279だけスクロールしています。巨大な問題ではありませんが、非常に迷惑で、何か間違っていることを指摘します。

だから、ここの質問は以下のとおりです。

  1. これは、水平スクロールを実装するための正しい方法ですか?そうでない場合は、何ですか?
  2. このデルタ0.279を削除するにはどうすればよいですか?

ありがとうございます。コードとscrollHorizo​​ntalでqDebug()ラインから

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

サンプル出力以下のサンプル出力シーンの左エッジで:

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 
+0

これは奇妙です。シーン矩形の境界に達したときに少し不自然にスクロールする 'QGraphicsView'が見つかりました。可視のrectがシーンrectにどこにあるかに関係なく同じ動作ですか? – cmannett85

+0

問題を引き起こしていることを知ることは興味深いですが、あなたがしていることは[UX](http://ux.stackexchange.com)の観点からはかなり悪いことです。誰かが水平スクロールを望むならば、それを実装した入力デバイスを単に使うことができます。最近のすべてのトラックパッド、スクロールパドルやマルチタッチなどのマウスのようなものです。おそらく、CADユーザーはまともな入力デバイスを用意する余裕があり、そのような回避策を用意する必要はありません。 –

答えて

5

あなたの問題はmapToScene()が整数を処理しているという事実から来ています浮動小数点ではなく、浮動小数点です。丸め誤差は、特定のビューポートサイズに対して常に同じ方法で指し示されるため、常にデルタを追加します。

スクロールバーのvalueプロパティを直接変更したり、イベントを水平スクロールバーに送信したりしたいとします。私は後者を実装しました、それは十分簡単です。

Macでは、アプリケーションのスクロールバーの慣性を絶対に無効にする必要があります。そうしないと、モディファイアを放してトラックパッド/スクロールホイールから指を離すとすぐに、垂直方向のスクロールが慣性により継続します。これは、Macユーザーの経験を吸うになるだろうと、彼らはそれのためにあなたを憎むだろう:)

screenshot

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(); 
} 
関連する問題