QGraphicsView: aktuellen Ausschnitt ermitteln

Alles rund um die Programmierung mit Qt
Antworten
shapoc
Beiträge: 33
Registriert: 31. Mai 2009 12:18

QGraphicsView: aktuellen Ausschnitt ermitteln

Beitrag 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?
Strahlex
Beiträge: 158
Registriert: 23. Dezember 2008 15:49
Wohnort: Österreich

Beitrag von Strahlex »

Mappe einfach die Eckpunkte des GraphicViews zur Scene:

Code: Alles auswählen

QPointF topLeftPoint = ui->graphicsView->mapToScene(ui->graphicsView->rect().topLeft());
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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)
shapoc
Beiträge: 33
Registriert: 31. Mai 2009 12:18

Beitrag 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...?
shapoc
Beiträge: 33
Registriert: 31. Mai 2009 12:18

Beitrag 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.
Strahlex
Beiträge: 158
Registriert: 23. Dezember 2008 15:49
Wohnort: Österreich

Beitrag 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!
shapoc
Beiträge: 33
Registriert: 31. Mai 2009 12:18

Beitrag 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.
Antworten