[solved] QGraphicsView: scene() an Fenster anpassen

Alles rund um die Programmierung mit Qt
Antworten
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

[solved] QGraphicsView: scene() an Fenster anpassen

Beitrag 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
Zuletzt geändert von franzf am 22. Januar 2008 13:36, insgesamt 1-mal geändert.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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?
Dateianhänge
chart_resizing_1.zip
(4.9 KiB) 98-mal heruntergeladen
Antworten