QGraphicsScene zeichnet nicht alle Items

Alles rund um die Programmierung mit Qt
Antworten
sanni
Beiträge: 39
Registriert: 27. Mai 2010 11:53

QGraphicsScene zeichnet nicht alle Items

Beitrag von sanni »

Ich benutzte in einem Programm ein QGraphicsScene-Objekt. In diese Scene zeichne ich mit

Code: Alles auswählen

scene->addPixmap( QBrush( image ) );
scene->addItem( item );  //wird ca 50 mal mit anderen Objekten wiederholt
erst ein QImage und dann die Items, welche von QGraphicsEllipseItem abgeleitet sind in die Scene.
Ich habe versucht, das Image als BackgroundBrush zu nutzen, aber leider wird es nicht von der oberen linken Ecke an gezeichnet, sondern scheinbar willkürlich irgendwie von der fast Mitte aus. Da ich das Bild aber als Hintergrund benötige, habe ich die scene->addPixmap()-Methode gewählt, die auch funktioniert.
Leider werden damit aber nicht alle Items, die dann folgen, in die Scene gezeichnet.

Nun also die Fragen:
1. Wie kriege ich es hin, dass mein Image von der linken oberen Ecke aus gezeichnet wird?
2. Warum werden nicht alle Items nach dem Pixmap in die Scene geschrieben?

Aufgrund der verschiedenen Layer wäre ja eigentlich die Methode scene->setBackgroundImage() am besten, denn dann werden alle Items korrekt gesetzt. Wenn das QImage dann nur richtig positioniert werden würde.
Gibt es eine andere Methode als QGraphicsScene->drawBackground() zu überschreiben?
phlox81
Beiträge: 97
Registriert: 7. Juli 2009 12:30
Kontaktdaten:

Beitrag von phlox81 »

Du solltest dich mal mit der Darstellung des Koordinatensystems in deiner Graphicscene beschäftigen. 0,0 liegt evtl. defaultmässig bei dir in der Mitte.

Die Korrekte Position für dein Bild wäre dann wahrscheinlich scenewidth/-2, sceneheight/-2
sanni
Beiträge: 39
Registriert: 27. Mai 2010 11:53

Beitrag von sanni »

Leider nein.
View und Scene sind von oben links nach unten rechts organisiert, nur die Items werden von der Mitte aus adressiert.
Das einsetzten der Items funktioniert ja auch mit der Adressierung (0,0)=links oben bestens.

Als BackgroundBrush könnte ich das Bild auch garnicht positionieren. Dazu müsste es ein GraphicsXXXItem sein.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

sanni hat geschrieben:Leider nein.
View und Scene sind von oben links nach unten rechts organisiert, nur die Items werden von der Mitte aus adressiert.
Das einsetzten der Items funktioniert ja auch mit der Adressierung (0,0)=links oben bestens.
Nein, stimmt leider so nicht. Bei Koordinaten auf nem QWidget ist das vllt. noch so, aber einer QGraphicsScene ist es wurscht wo du anfängst. Du kannst ein Item nach (-100, -200) verschieben, dann fängt halt die scene entsprechend im negativen Bereich an (der genaue Punkt hängt wiederum von den boundingRects der einzelnen Items ab). Zuständig ist eigentlich das sceneRect().
Damit ist auch klar, dass (0, 0) nicht unbedingt das Zentrum sein muss.

Zu deinen Fragen:
1) Koordinaten korrekt berechnen
2) Mit ZValue der Items spielen.

- setBackgroundImage gibt es nicht
- QBrush([image|pixmap]) zeichnet eine Textur, wiederholt also dein Bild ganz oft neben/untereinander.
sanni
Beiträge: 39
Registriert: 27. Mai 2010 11:53

Beitrag von sanni »

Sorry ich habe ja auch versuchsweise die Funktion setBackgroundBrush() benutzt, um das Bild als Background einzusetzen.
Mit welcher Funktion kann ich denn das BackgroundBrush verschieben? Ich habe mir da schon die Augen ausgeguckt, aber nichts gefunden.

Und warum werden die items nicht alle gezeichnet?
Vor allem die ersten 20 erscheinen nicht auf dem Pixmap in der scene, der Rest erscheint nicht komplett.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

sanni hat geschrieben:Sorry ich habe ja auch versuchsweise die Funktion setBackgroundBrush() benutzt, um das Bild als Background einzusetzen.
Mit welcher Funktion kann ich denn das BackgroundBrush verschieben? Ich habe mir da schon die Augen ausgeguckt, aber nichts gefunden.
QGraphicsScene zeichnet den Brush vom Ursprung (0,0) aus. Willst du das verschieben, musst du beim QBrush ansetzen. Genauer: QBrush per setTransform() mit einem QTransform::translate() "verschieben". Ist aber sicherlich nicht so leicht, da deine scene evtl. kleiner als die view ist, kann es durchaus sein, dass wieder das Bild nicht links oben beginnt. MMn. einzige Lösung: Von QGraphicsView ableiten, und drawBackground() selber implementieren.

(Ich glaube du willst dir ja einen SpaceShooter schreiben, da hat deine Fenster eine statische Größe, hier solltest du mit Transformiertem Brush ans Ziel kommen.)
Und warum werden die items nicht alle gezeichnet?
Vor allem die ersten 20 erscheinen nicht auf dem Pixmap in der scene, der Rest erscheint nicht komplett.
Ohne Code kann man dazu nichts sagen. Überlappende Items, irgendwelche lustigen Flags, falsches boundigRect(), etc. Ein Screenshot wäre nicht schlecht, damit man sieht wie der Fehler ausschaut.
sanni
Beiträge: 39
Registriert: 27. Mai 2010 11:53

Beitrag von sanni »

Nein, das Programm ist viel banaler. Eine Abbildung der Küste Deutschlands, auf der alle Leuchttürme genau so blinken, wie sie in der Realität blinken. Also nach der offiziellen Kennung. (Eine gute Möglichkeit, in die Graphics-Programmierung einzusteigen)

Dazu habe ich die Leuchttürme einfach von QGraphicsEllipseItem abgeleitet und das Ein- und Ausschalten in einer Timeline realisiert. Diese wird so oft wiederholt, wie das Blinken benötigt wird. Die gesamte Signaldauer wird dann durch einen Timer wiederholt angestoßen.
Im Item wird das Blinken einfach durch die Methode setVisible() realisiert.

Das Widget, in dem die Karte gezeichnet wird, habe ich so realisiert:

Code: Alles auswählen

Karte::Karte( QWidget *parent ) : QWidget( parent ){
  scene = new QGraphcisScene();
  scene->addPixmap( QPixmap( "kueste.jpg" );

  QGraphicsView *view = new QGraphicsView( this );
  view->setScene( scene );
  view->resize( 1000, 490 );
  view->show();
  initTuerme();
}
In der Funktion initTuerme() habe ich die Punkte dann nacheinander mit

Code: Alles auswählen

scene->additem( new Turm( x-Wert, y-Wert, Kennung ) ); //insgesamt 50 Mal
. . .
eingefügt. scene ist in der Header-Datei deklariert.

Also keine Faxen mit irgendwelchen Flags oder Rects. Die Türme überlagern sich auch nicht.
Die Positionierung der Türme funktioniert einwandfrei wie schon beschrieben. Das Einbinden der Karte mit addPixmap() hat den Vorteil, dass die Laufbalken an der Seite automatisch erscheinen.
Antworten