Seite 1 von 1

[solved] QGraphicsView: scene() an Fenster anpassen

Verfasst: 21. Januar 2008 20:35
von franzf
Hallo Leute,

Ich habe ein kleines Problem. Ich möchte meinem GraphicsView ein FitWidth/FitHeight/FitPage verpassen. Letzteres funktioniert prächtig, bei den beiden anderen habe ich noch Probleme. Es werden wie wild neue resizeEvents abgefeuert, wenn das Größenverhältnis der Seiten ScrollBars erfordert.
Auf Folgendes konnte ich mich in meinem resizeEvent einigen:

Code: Alles auswählen

void
View::resizeEvent(QResizeEvent* e)
{
    static int i = 0;
    i++;
    qDebug() << "resizeEvent() triggered: " << i;
    int margin = 2;
    //QRect viewRect = QRect(QPoint(0, 0), e->size()).adjusted(margin, margin, -margin, -margin);
    //QRect viewRect = viewport()->rect().adjusted(margin, margin, -margin, -margin);
    //QRect viewRect = viewport()->rect();
    QRect viewRect = QRect(QPoint(0,0), e->size());
    //QRect viewRect = rect();
    if( _resizeMode == Chart::FitWidth ) {
        _zoom = viewRect.width()/scene()->width();
    } else if( _resizeMode == Chart::FitHeight ) {
        _zoom = viewRect.height()/scene()->height();
    }
    //QGraphicsView::resizeEvent(e);
}
An den vielen viewRect sieht man meine gescheiterten Versuche. nur die letzte (gerade auskommentierte) Zeile klappt, allerdings hab ich dann immer Scrollbars, was ich ja genau nicht will.
Den Zähler hab ich eingebaut um zu sehen was da so abgeht, innerhalb 3-4 Sekunden (ohne Fenstergröße verändern!) bin ich auf über 1000 Events!

Mein paintEvent schaut dann so aus:

Code: Alles auswählen

void
View::paintEvent(QPaintEvent* e)
{
    QGraphicsView::paintEvent(e);
    if( _resizeMode == Chart::FitPage ) {
        fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
    } else {
        updateZoom();
    }
}
Wobei updateZoom() folgendes macht:

Code: Alles auswählen

void
View::updateZoom()
{
  QMatrix matrix;
  matrix.scale(_zoom, _zoom);
  setMatrix(matrix);
}
Kann mir jemand sagen wo mein Fehler liegt? Es hilft übrigens auch nix wenn ich das QGraphicsView::resizeEvent(e) einfüge, auch am Anfang von resizeEvent...
Bin grad relativ am Ende mit meinem Latein.

Es wäre sehr nett wenn mir jemand von euch weiterhelfen könnte...

Besten Dank
Franz

Verfasst: 22. Januar 2008 13:34
von franzf
Ok, hab es lösen können - ein Tag voller Pein ;). Die Ursache für mein Problem war, dass wenn die Scene nicht komplett in mein view passte die view automatisch ScrollBars einfügte. Mit dem ScrollBar war jetzt im viewport() wieder genügend Platz, um die scene() komplett anzuzeigen, weswegen diese wieder entfernt werden wollten, und so weiter.
Lösen konnte ich es nur indem ich eben alle Fälle von
Scrollbar vorhanden? -> brauch ich eine Scrollbar?
abarbeiten musste und die Scrollbars dann entsprechend einzeln auf visible() setzen oder nicht.

Die entscheidenden Methoden schauen dann so aus:

Code: Alles auswählen

void
Chart::setResizeMode(ResizeMode mode)
{
  _resizeMode = mode;
  if(_resizeMode == Chart::UserZoom) {
    setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  } else if(_resizeMode == Chart::FitWidth) {
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  } else if(_resizeMode == Chart::FitHeight) {
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  } else if(_resizeMode == Chart::FitPage) {
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  } else {
    qDebug() << "No correct ResizeMode was given";
  }
  if(_resizeMode == Chart::UserZoom) {
    updateZoom();
  } else {
    QResizeEvent* event = new QResizeEvent(viewport()->size(), viewport()->size());
    QCoreApplication::postEvent(viewport(), event);
  }
}

void
Chart::resizeEvent(QResizeEvent* e)
{
  static int i = 0;
  i++;
  qDebug() << "resizeEvent() triggered: " << i;
  if( _resizeMode == Chart::FitWidth ) {
    if(verticalScrollBar()->isVisible()) {
      if((rect().width()-2*frameWidth())/scene()->width() < (rect().height()-2*frameWidth())/scene()->height()) {
        // we don't need ScrollBars anymore
        verticalScrollBar()->setVisible(false);
        _zoom = (rect().width()-2*frameWidth())/scene()->width();
      } else {
        // we have ScrollBars and need them
        // but we need to make sure they are visible
        verticalScrollBar()->setVisible(true);
        _zoom = (rect().width()-style()->pixelMetric(QStyle::PM_ScrollBarExtent)-2*frameWidth())/scene()->width();
      }
    } else {
      // we don't have visible ScrollBars
      if((rect().width()-2*frameWidth())/scene()->width() < (rect().height()-2*frameWidth())/scene()->height()) {
        // the scene fit'a perfectly into the view, without ScrollBars
        verticalScrollBar()->setVisible(false);
        _zoom = (rect().width()-2*frameWidth())/scene()->width();
      } else {
        // We need Scrollbars
        verticalScrollBar()->setVisible(true);
        _zoom = (rect().width()-style()->pixelMetric(QStyle::PM_ScrollBarExtent)-2*frameWidth())/scene()->width();
      }

    }
    updateZoom();
  } else if( _resizeMode == Chart::FitHeight ) {
    if(horizontalScrollBar()->isVisible()) {
      if((rect().height()-2*frameWidth())/scene()->height() < (rect().width()-2*frameWidth())/scene()->width()) {
        horizontalScrollBar()->setVisible(false);
        _zoom = (rect().height()-2*frameWidth())/scene()->height();
      } else {
        horizontalScrollBar()->setVisible(true);
        _zoom = (rect().height()-style()->pixelMetric(QStyle::PM_ScrollBarExtent)-2*frameWidth())/scene()->height();
      }
    } else {
      if((rect().height()-2*frameWidth())/scene()->height() < (rect().width()-2*frameWidth())/scene()->width()) {
        horizontalScrollBar()->setVisible(false);
        _zoom = (rect().height()-2*frameWidth())/scene()->height();
      } else {
        horizontalScrollBar()->setVisible(true);
        _zoom = (rect().height()-style()->pixelMetric(QStyle::PM_ScrollBarExtent)-2*frameWidth())/scene()->height();
      }
    }
    updateZoom();
  } else if(_resizeMode == Chart::FitPage) {
    fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
  }
  QGraphicsView::resizeEvent(e);
}

void
Chart::paintEvent(QPaintEvent* e)
{
  QGraphicsView::paintEvent(e);
  if( _resizeMode != Chart::FitPage && _resizeMode != Chart::UserZoom ) {
    updateZoom();
  }
}
Ich hab auch noch (für alle Compile-willigen) ein ganzes funktionierendes Beispiel angehangen. Verwende zwar CMake, klappt aber sicher auch mit qmake ;)
Vielleicht kann das ja einer der Cracks noch kurz anschauen, ob man das auch alles wirklich so machen sollte, denn nicht alles was funktioniert ist auch gut so...

Besten Dank
Franz


// edit:
Gibt es einen Grund warum das Anhängen von .bz2 verboten ist?