Seite 1 von 1

QGraphicsView: aktuellen Ausschnitt ermitteln

Verfasst: 13. Juni 2009 13:45
von shapoc
Ich muss nochmal eine Anfängerfrage stellen, weil ich einfach nicht weiterkommen!

Ich möchte für meine QGraphicsScene + View folgendes erreichen: wenn ich bis zum Rand der Scene mit meinem View scrolle (oben,unten,links,rechts) möchte ich das erkennen und auf der entsprechenden Seite neue QGraphicItems zeichnen. Ziel soll eine "unendliche" Scene sein, die beim nach-rechts-scrollen die Items von der linken Seite rechts hinzufügt.

Mein Problem ist, dass ich den aktuellen Ausschnitt nicht bekomme. Habe es im View mit sceneRect() und mapToScene versucht, aber keinen Erfolg gehabt!

Könnt ihr mir weiterhelfen?

Verfasst: 13. Juni 2009 14:17
von Strahlex
Mappe einfach die Eckpunkte des GraphicViews zur Scene:

Code: Alles auswählen

QPointF topLeftPoint = ui->graphicsView->mapToScene(ui->graphicsView->rect().topLeft());

Verfasst: 13. Juni 2009 14:30
von franzf
Oder (mal wieder ;) ) über die Scrollbars.
In nem Slot deiner Klasse, die die GV verwaltet, auf die scrollBars deiner View connecten. Wenn die aktuelle Scrollbarposition an ein Ende kommt einfach die Scene erweitern mit neuen Elementen.

Ich würd mich aber trotzdem nicht nur (zu sehr) auf die Scrollbars verlassen. Die Scrollbars, wenn sie da sind, schauen auf die Scene->sceneRect(). Und, naja, Das sceneRect kann auch größer sein als dder Bereich, den alle sichtbaren Items einnehemen. Lies dir die Doku mal zu sceneRect und setSceneRect durch und experimentier bissl.
(Das war zu mindest vor nem halben Jahr, als ich da mal in dumme Sachen gerennt war, so. Ich denke aber da hat sich nix geändert :P)

Verfasst: 13. Juni 2009 16:51
von shapoc
Danke für eure Hinweise.

@Strahlex: Ich hatte noch einen anderen Denkfehler drin, weswegen ich die Scene in die negative x und y Richtung aufgebaut hatte. Deshalb bekam ich so komische Koordinaten zurück (-41000, -41000) und war verwirrt!

Mit mapToScene funktioniert's!

@franzf: Ich hab das sceneRect nicht manuell gesetzt. Laut Doku umfasst es die äußere Begrenzung aller Items, was sich auch im scrollen bemerkbar macht. Ich kann nur bis zum "Rand" scrollen, also bis zum letzten Bild in jede Richtung. Zoomen habe ich aber manuell implementiert, weswegen das auch weiter geht.

Was ich grad ausprobiert hab ist folgendes. Ich prüfe erstmal auf der linken Seite, ob mein view die linke Seite erreicht. Falls ja, erstelle ich ein neues QGraphicsItem und zeichne es an die Position topLeftPoint.x-100/topLeftPoint.y .
Jetzt habe ich das Problem, dass sich die Scene nicht automatisch vergrößert, sprich ich kann trotzdem nicht weiterscrollen.

Habe versucht, nach dem Hinzufügen des Items per invalidateScene und update der Scene beizubringen, dass sie größer ist: vergebens.
Muss ich setSceneRect dann manuell aufrufen und mit den neuen Werten versorgen oder gibts noch was eleganteres...?

Verfasst: 13. Juni 2009 18:57
von shapoc
OK, denke ich hab jetzt nen Weg gefunden, mit dem es funktioniert.
In der MouseMoveEvent Methode mache ich folgendes:

Code: Alles auswählen

		QPointF topLeftPoint = mapToScene(rect().topLeft());
		if (topLeftPoint.x() <= sceneRect().x()+100)
		{
			//QMessageBox::about(this, tr("scene rect"),  QString("left: %1 right: %2").arg(topLeftPoint.x()).arg(topLeftPoint.y()));
			QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(QPoint(0,0), QPoint(100,100)));

			item->setPos(QPointF(topLeftPoint.x()-100, topLeftPoint.y()-100));
			
			scene()->addItem(item);
			scene()->setSceneRect(sceneRect().x()-150, sceneRect().y()-150, sceneRect().width()+150, sceneRect().height()+150);
			invalidateScene (QRectF(), QGraphicsScene::AllLayers); 
			update();
		}
Damit prüfe ich, ob ich kurz vor dem linken Rand bin. Wenn ja, dann zeichne ich 100px links davon ein neues Item.
Jetzt muss ich eigentlich nur noch die Items am rechten Rand auswählen und dann hierher verschieben.

Verfasst: 14. Juni 2009 00:11
von Strahlex
Müsste funktionieren, das gleiche wirst du wohl auch noch für die anderen Seiten machen müssen.

PS:
shapoc hat geschrieben:

Code: Alles auswählen

			//QMessageBox::about(this, tr("scene rect"),  QString("left: %1 right: %2").arg(topLeftPoint.x()).arg(topLeftPoint.y()));
			
Schau dir doch mal QDebug in der Doku an!

Verfasst: 14. Juni 2009 12:23
von shapoc
Ja klar, qDebug hab ich mir schon angeguckt. Das war noch ne alte Ausgabe und dummerweise nur auskommentiert, anstatt gelöscht :oops:

Hab grad noch das Problem, dass ich beim diagonal verschieben zwei werte überprüfen muss und das anscheinend noch nich so richtig synchron is... Werd noch ein bischen rumprobieren müssen, aber im Prinzip funktionierts.