Seite 1 von 1

Rotierendes QGraphicsView

Verfasst: Samstag 3. August 2013, 12:07
von bob
Moin,

ich versuche schon seit einiger Zeit ein rundes, um den Mittelpunkt rotierendes QGraphicsView zu erstellen. (Es soll dann als Overlay dienen) Das Problem ist: es "eiert" um den Mittelpunkt und ich bekomme es einfach nicht zentreiert und kann das Problem nicht erkennen.

Frage: Wie bekomme ich den Rotationsmittelpunkt in der Abbildung zentriert?
Hat hier jemand eine Idee?

Code: Alles auswählen

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Overlay(QWidget):
	def __init__(self,parent=None):
		QWidget.__init__(self,parent)
		self.height = parent.size().height()/2
		self.width = parent.size().width()/2
		self.setGeometry(80,20,self.height, self.height)
		
		scene = QGraphicsScene(0,0,self.height,self.height)
		scene.addItem(self.create_letter())
		
		scene.addEllipse(0, 0, self.height ,self.height, QPen(Qt.NoPen), QBrush(QColor(0,129,94,40)))
		
		self.view = QGraphicsView(self)
		self.view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
		self.view.setStyleSheet("background: rgba(100,100,100,50); border: transparent")
		
		self.view.setScene(scene)
		
	def create_letter(self):
		n = self.height
		group = QGraphicsItemGroup()
		txt = QGraphicsTextItem("N")
		txt.setFont(QFont("Arial", 20))
		txt.translate(n/2-14, 30)
		group.addToGroup(txt)
		
		txt = QGraphicsTextItem("E")
		txt.setFont(QFont("Arial", 20))
		txt.translate(n-30, n/2 - 13)
		txt.setRotation(90)
		group.addToGroup(txt)
		
		txt = QGraphicsTextItem("S")
		txt.setFont(QFont("Arial", 20))
		txt.translate(n/2+13, n - 30)
		txt.setRotation(180)
		group.addToGroup(txt)
		
		txt = QGraphicsTextItem("W")
		txt.setFont(QFont("Arial", 20))
		txt.translate(30, n/2 + 16)
		txt.setRotation(270)
		group.addToGroup(txt)
		
		return group
	
	def rot_compass(self, angle=0):
		self.view.rotate(80)

class Main(QWidget):
	def __init__(self):
		QWidget.__init__(self)
		self.setGeometry(300,300,600,400)
		
		self.overlay = Overlay(self)
		
		self.t()
		
	def paintEvent(self, event):
		path = QPainterPath()
		path.addRoundRect(0,0,500,380,25)
		
		painter = QPainter(self)
		pen = QPen(QColor(90,90,90))
		pen.setWidth(2)
		painter.setBrush(QColor(248,241,225))
		painter.setPen(pen)
		painter.drawPath(path)
		
	def t(self):
		print("Timer start")
		self.timer = QTimer(self)
		self.connect(self.timer, SIGNAL("timeout()"), self.overlay.rot_compass)
		self.timer.start(1000)


app = QApplication(sys.argv)
m = Main()
m.show()
sys.exit(app.exec_())
Mit freundlichen Grüßen,

Bob

Re: Rotierendes QGraphicsView

Verfasst: Montag 12. August 2013, 22:11
von bob
Guten Abend liebes Forum,

weiß den keiner Rat, oder konnte ich mein Anliegen nicht genau genug darlegen?
Hat sonst denn jemand eine andere Idee wie ich mein Overlay erstellt bekomme? Ich dachte nur mit dem QGraphicsView ist das am Resourcenschonendsten.

Mfg
bob

Re: Rotierendes QGraphicsView

Verfasst: Dienstag 13. August 2013, 13:54
von lunar
@bob Ein GraphicsView transformiert standardmäßig um das Zentrum der Szene. Das Problem liegt bei Dir eher nicht im GraphicsView selbst, sondern im ziemlich abstrusen Layout Deiner Fenster. Ich nehme mal an, dass der GraphicsView eben nicht genau in der Mitte angezeigt wird, was dann zum Eindruck führt, die Transformation der Szene wäre fehlerhaft.

Nutze doch bitte Layouts statt fester Größenangaben, dehne mithilfe des Layouts den GraphicsView über die gesamte Größe des Overlaywidgets aus, zentriere dann die Szene um das zentrale Item. Konsultiere die Qt-Dokumentation zu den Details, insbesondere die Abschnitte über Layouts, und über die verschiedenen Koordinatensystem in einem QGraphicsView.

Re: Rotierendes QGraphicsView

Verfasst: Dienstag 13. August 2013, 15:00
von bob
Danke für den Hinweis.
Dann werde ich das mal so probieren.

bob

Re: Rotierendes QGraphicsView

Verfasst: Freitag 23. August 2013, 12:20
von Madmartigan
Ich halte es zwar für unnötig, in deinem Falle den ganzen View rotieren zu wollen, aber wer weiß, was du damit letztendlich planst. :K

Prinzipiell würde ich eher das Item/die Group rotieren. Damit das Ganze dann auch konzentrisch rotiert, bietet sich die Verwendung von QGraphicsItem.setTransformOriginPoint (qreal x, qreal y) an. Damit kannst du die Rotationsachse einfach ins Zentrum deiner Group setzen und diese dann um sich selbst rotieren lassen. Um das ganze auch wirklich zu verstehen, ist es ratsam, sich (wenigstens!) die Basics über Matrizen und Verwendung von verschiedenen Koordinatensystemen anzueignen.

Falls das Ganze in Richtung "Spiel" gehen sollte, rate ich dir dringend von festen/absoluten Größenangaben und Positionen ab. Wie Lunar schon sagte, für deine UI nutzt du am besten Layouts, die sind sehr mächtig und nehmen dir unglaublich viel ab. Für den GraphicsView gibt es unzählige Beispiele im Netz, vielleicht schaust du dir die an und adaptierst davon.

Re: Rotierendes QGraphicsView

Verfasst: Montag 26. August 2013, 17:27
von bob
@Madmartigan Danke für den Tip. Ich rotiere die Group mit setRotation(), was mit QGraphicsItem.setTransformOriginPoint (qreal x, qreal y) wunderbar funktioniert. Warum das mit dem einfachen rotate() nicht funktioniert - wie auch in meinem obigen Versuch - ist mir zwar immer noch nicht klar, vermute aber das liegt an meinem Unvermögen die verschiedenen Koordinatensysteme in einklang zu bringen und den Ursprung zu setzen.

Es soll tatsächlich nur eine Kompassrose werden, die dann als Overlay gesetzt wird, und entsprechend den einfließenden Daten eben ständig rotieren muss. Der Umbau in Layouts erfolgt schon Stück für Stück, nur finde ich es persöhnlich verständlicher, wenn ich beim Aufbau des Widgets zunächst mal absolute Werte habe, bei deren Veränderung ich dann auch den Effekt sehe.