QtGraphicsItemGroup nicht sichtbar

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
the-me
User
Beiträge: 7
Registriert: Donnerstag 5. Juli 2012, 19:55

Hallo zusammen,

ich bin neu hier, schon recht lange mit Python unterwegs, aber neu mit PySide verbandelt. Jetzt möchte ich mehrere Elemente zusammenfassen zu einem einzelnen mit Hilfe einer QGraphicsItemGroup. Und das funktioniert nicht - die Group ist nicht sichtbar. Vielleicht ein Beispiel. Das unten funktioniert bestens:

Code: Alles auswählen

def fill_group_with_full_rose_compass(scene, size=400):
   def do_lines(length, delta, no_line, pen):
      for angle in [l*delta for l in range(360/delta)]:
         if angle in no_line:
            continue
         line = QGraphicsLineItem(size/2,0, size/2,length)
         line.setTransformOriginPoint(size/2, size/2)
         line.setRotation(angle)
         line.setPen(pen)
         scene.addItem(line)
   pen = QPen(Qt.black, size/200, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/8, 30, [], pen)
   pen = QPen(Qt.black, size/400, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/12, 10, [a*30 for a in range(12)], pen)
   pen = QPen(Qt.black, size/400, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/20, 5, [a*10 for a in range(36)], pen)

if __name__ == '__main__':
   app = QApplication(sys.argv)
   scene = QGraphicsScene()

   fill_group_with_full_rose_compass(scene, 400)
Wenn ich es wie unten modifiziere - dann kommt ein leeres Fenster. Weiß jemand warum??

Code: Alles auswählen

def fill_group_with_full_rose_compass(group, size=400):
   def do_lines(length, delta, no_line, pen):
      for angle in [l*delta for l in range(360/delta)]:
         if angle in no_line:
            continue
         line = QGraphicsLineItem(size/2,0, size/2,length)
         line.setTransformOriginPoint(size/2, size/2)
         line.setRotation(angle)
         line.setPen(pen)
         group.addToGroup(line)
         #group.addItem(line)
   pen = QPen(Qt.black, size/200, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/8, 30, [], pen)
   pen = QPen(Qt.black, size/400, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/12, 10, [a*30 for a in range(12)], pen)
   pen = QPen(Qt.black, size/400, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
   do_lines(size/20, 5, [a*10 for a in range(36)], pen)

if __name__ == '__main__':
   app = QApplication(sys.argv)
   scene = QGraphicsScene()

   compass = QGraphicsItemGroup()
   fill_group_with_full_rose_compass(compass, 400)
   scene.addItem(compass)
Bin für jede Hilfe dankbar :) .


Grüße!
Axel.
Zuletzt geändert von the-me am Samstag 7. Juli 2012, 17:22, insgesamt 1-mal geändert.
lunar

@the-me: Du brauchst ein "QGraphicsView"-Steuerelement zur Anzeige einer "QGraphicsScene".
the-me
User
Beiträge: 7
Registriert: Donnerstag 5. Juli 2012, 19:55

ja, hm, also die Scene wird ja sehr gut dargestellt, nur nicht wenn ich ein QGraphicsItemGroup darin platziere.

Ich hatte die letzten Zeilen weggelassen:

Code: Alles auswählen

# ....   
   view = QGraphicsView(scene)
   view.setRenderHints(QPainter.Antialiasing or QPainter.SmoothPixmapTransform)
   if NO_INDEX:
      view.setItemIndexMethod(QGraphicsScene.NoIndex);
   if OPTIMIZE:
      view.setOptimizationFlags(QGraphicsView.DontAdjustForAntialiasing
                                or QGraphicsView.DontClipPainter
      or QGraphicsView.DontSavePainterState)

   view.show()
   sys.exit(app.exec_())
Also ich denke nicht, dass es daran liegt ...
lunar

@the-me: Zeige gleich vollständigen Quelltext, dann erhältst Du auch sofort eine vernünftige Antwort.

So wie ich die Doku verstehe, dient QGraphicsItemGroup nur dazu, bereits in der Szene vorhandene Elemente zu gruppieren, nicht aber neue hinzuzufügen. Mithin musst Du wohl jedes QGraphicsItem nochmals explizit der Szene hinzufügen. Ich würde eine Funktion schreiben, die mir alle Items erzeugt ohne sie der Szene hinzufügen (i.e. "compass= createCompassItems()"), diese Items anschließend der Szene hinzufügen ("for item in compass: scene.addItem(item)") und schlussendlich gruppieren ("group = scene.createItemGroup(items)").

Anstelle einer Gruppe kannst Du auch überlegen, ob Du nicht vielleicht ein "QGraphicsItem" als Vater für alle anderen Items verwenden kannst, oder ob Du die Grafik vielleicht sogar als Pfad (siehe QGraphicsPath) ausdrücken kannst, dann reicht ein "QGraphicsPathItem".
the-me
User
Beiträge: 7
Registriert: Donnerstag 5. Juli 2012, 19:55

Hm, das mit dem doppelten hinzufügen glaube ich nicht ...
There are two ways to construct an item group. The easiest and most common approach is to pass a list of items (e.g., all selected items) to QGraphicsScene::createItemGroup(), which returns a new QGraphicsItemGroup item. The other approach is to manually construct a QGraphicsItemGroup item, add it to the scene calling QGraphicsScene::addItem(), and then add items to the group manually, one at a time by calling addToGroup().
Aber ich kann es ja mal versuchen. Wenn ich dann versuche, die group zu bewegen, dann sollte ja was passieren - und wenn nix passiert war's das auch nicht.
lunar

@the-me: Du hast recht: Ich habe Dein Beispiel ausprobiert, und erhalte einen Kompass auch ohne doppeltes Hinzufügen der Elemente. Falls dieser Quelltext nicht mit PySide funktioniert, dann handelt es sich um einen Bug in PySide, und Du musst Dich an die Mailingliste des Projekts wenden.

Übrigens habe ich trotz n=5000 keine Performance-Probleme beim Zeichnen der Linien.

Beim Aufräumen Deines Quelltexts ist mir aufgefallen, dass Du eine ungewöhnliche Einrückung nutzt. Du machst Dir das Programmieren einfacher, wenn Du Dich an die Norm von vier Leerzeichen pro Ebene hältst, da Du dann beispielsweise Quelltext aus dem Netz kopieren kannst, ohne erst dessen Einrückung anpassen zu müssen.

Gestolpert bin ich auch über "QPainter.Antialiasing or QPainter.SmoothPixmapTransform". "or" ist eine logische, keine bitweise Verknüpfung, dieser Ausdruck ergibt mithin nicht die Kombination beider Flags, sondern immer nur "QPainter.Antialiasing", da "or" den linken Operanden zurückgibt, wenn dieser im boolschen Kontext nicht zu "False" ausgewertet wird. Richtig wäre "QPainter.Antialiasing | QPainter.SmoothPixmapTransform".
the-me
User
Beiträge: 7
Registriert: Donnerstag 5. Juli 2012, 19:55

Ah mit PyQt funktionierts? Mist :) . Okay, ich werde es mal den PySide Jungs melden.

Das mit den 4 Zeichen stört mich einfach. Und ja, das ist etwas ungeschickt, aber ein auto-Formatter erledigt das dann auch. Das mit der Performance und der Verknüpfung unten ist schlichtweg aus einem Beispiel rauskopiert und ziemlich toter Code, der einfach von mir noch nicht genauer angeschaut wurde. (das mit n=1000 hatte ich einfach vergessen zu löschen, der Ursprungs-Poster hatte irgendein Problem aber mit vollkommen anderem Code). Und du hast natürlich Recht - "or" ist ziemlicher Schwachsinn da unten. Aber wie gesagt - ich wollte erst mal einfach nur ein paar Linien zeichnen.

Danke für deine Mühe!
lunar

@the-me: Ich habe nicht ausprobiert, ob Dein ursprünglicher Quelltext mit PyQt funktioniert, sondern nur meinen eigenen Quelltext getestet. Probiere diese Version nochmal aus, bevor Du Dich an PySide wendest.

Was stört Dich denn an vier Leerzeichen, was Dich an drei(!) Leerzeichen nicht stört?! Nicht böse gemeint, aber die Begründung finde ich doch etwas seltsam ;) Ich würde Dir übrigens raten, in zukünftigen Beiträgen hier den Quelltext vorher neu zu formatieren, so dass er vier Leerzeichen verwendet, sonst wirst Du Anmerkungen zur "falschen" Einrückung immer wieder hören :)
the-me
User
Beiträge: 7
Registriert: Donnerstag 5. Juli 2012, 19:55

Klappt auch mit deinem Code nicht. Und ich ertrage lieber ab und zu einen Kommentar, als ständig ein Leerzeichen "zu viel" in meinem Code. Vier sind einfach zu viel finde ich ;)
Antworten