2013-05-10 27 views
6

Ho sottoclasse QGraphicsView per un canvas personalizzato da utilizzare in un'applicazione CAD. Ho reimplementato con successo QGraphicsView :: wheelEvent per controllare i modificatori della tastiera per il tasto control e, se si preme il tasto control, per eseguire lo zoom. Sto cercando di implementare una scroll orizzontale quando l'utente tiene il turno e usa la ruota.qgraphicsview lo scrolling orizzontale ha sempre un delta verticale

Il problema che sto avendo è che lo scorrimento orizzontale anche sempre scorre verso l'alto di 0,279. Non è un problema enorme, ma estremamente fastidioso e indica che qualcos'altro è sbagliato.

Quindi, ecco le domande:

  1. E 'questo il modo giusto per implementare lo scorrimento orizzontale? Se no, che cos'è?
  2. Come eliminare questo delta di 0,279?

Grazie in anticipo. Codice e campione di uscita sotto

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

uscita campione dalla linea qDebug() in scrollHorizontal quando al bordo sinistro della scena:

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

Questo è strano. Trovo che 'QGraphicsView' scorra un po '' innaturale 'quando raggiungi i limiti del rettangolo di scena, il comportamento è lo stesso indipendentemente da dove il rect visibile si trova nella scena rect? – cmannett85

+0

Mentre sarebbe interessante sapere che cosa sta causando il problema, quello che stai facendo è piuttosto negativo dalla prospettiva [UX] (http://ux.stackexchange.com). Se qualcuno vuole uno scroll orizzontale, può semplicemente usare un dispositivo di input che lo ha implementato. Come tutti i trackpad recenti, mouse con padiglioni di scorrimento o multitouch, ecc. Presumibilmente, un utente CAD può permettersi un dispositivo di input decente e non è necessario offrire tali soluzioni alternative. –

risposta

5

tuo problema deriva dal fatto che mapToScene() processi un numero intero punto, non un punto in virgola mobile. L'errore di arrotondamento viene sempre indicato allo stesso modo per una particolare dimensione del viewport, quindi aggiungi sempre delta.

Si desidera modificare direttamente la proprietà value della barra di scorrimento o inviare l'evento alla barra di scorrimento orizzontale. Ho implementato quest'ultimo, è abbastanza semplice.

Su un Mac, è necessario disattivare completamente l'inerzia della barra di scorrimento per l'applicazione. Altrimenti, non appena si rilascia il modificatore e si solleva il dito dal trackpad/ruota di scorrimento, lo scorrimento verticale continuerà a causa dell'inerzia. Questo renderebbe l'esperienza degli utenti Mac succhiare e sarebbero odieranno per questo :)

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(); 
} 
Problemi correlati