Seite 1 von 1

Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 27. Mai 2013 16:52
von Abayo
Hi @ all!

Ich bin noch recht neu in Qt und hoffe das Ihr mir bei ein paar Problemen helfen könnt (oder in die richtige Richtung stoßen).

Ich möchte eine kleine Animation machen bei der ich auf einem png-Hintergrund ein zweites png bewegen möchte (z.B. ein Kreis als Hintergrund und ein Zeiger der sich dreht). Das habe ich auch schon über PaintEvent mit einem QPainter in einem QWidget hinbekommen.
Nun möchte ich das ganze mehr aufsplitten um die einzelnen Aufgaben zu verteilen und um das Objektorientierte Programmieren besser ausnutzen. Dazu wollte ich diesselben Funktionen auf eine Basisklasse und eine davon abgeleitete Klasse aufteilen.
Die Basisklasse soll alle starren Dinge erledigen (Fenstergröße, Hintergrund, usw..) und die abgeleitete Klasse dann das animierte Objekt (der Zeiger). Hintergrund für diese Herangehensweise: später möchte ich andere abgeleitete Klassen machen, die andere Objekte in dem Kreis drehen/bewegen. Dabei möchte ich aber immernoch die Kontrolle darüber haben, damit ich z.B. spontan die Farbe ändern kann.

Soweit meine Überlegungen. Nun habe ich das Problem das die abgeleitete Klasse das im PaintEvent der Basisklasse gezeichnete Hintergrundbild wieder übermalt. Auch ein Aufruf Basisklasse::update() hatt mir da nicht weiterhelfen können.

Kennt Ihr ein solches Problem? Wie kann ich das in der basisklasse gezeichnete Bild dauerhaft anzeigen und sozusagen "versiegeln", sodass ich noch darauf zeichnen kann, aber das Bild immer da bleibt?

Desweiteren bin ich mir nicht sicher ob QWidget dafür die beste Wahl ist. Hat jemand von euch erfahrung mit solchen Animationen? Gibt es einen besseren Weg?
Ich möchte das ganze später so weit führen dass ich auf einer Grundfläche mehrere eigene Widgets anzeige und diese alle voneinander unabhängig animieren (deswegen die aufsplittung. Basisklasse + abgeleitete Klasse = ein Widget). So etwas wie eine Ofenanzeige oder ein Amaturenbrett (wäre ja dann sehr wandelbar) :)

Ich hoffe ich habe euch nun kein Ohr abgekaut ;) und dass Ihr mir helfen könnt bzw. gute Ideen habt wie ich anders an diese Projekt herangehen könnte.

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 27. Mai 2013 18:54
von veeman
Schau dir mal QGraphicsView und QGraphicsItem an.

Basisklasse::update() ist an der stelle wohl fehl am Platz. Da du paintEvent erwähnst dann nehme ich auch an das du deine Zeichenmethode in der paintEvent-Methode durchführst. [->paintEvent(QPaintEvent *event)]
Um die von der Basisklasse durchgeführte Zeichenroutine durchzuführen musst du auch paintEvent aufrufen und nicht update.
Update signalisiert nur dass sich das Widget neu zeichnen soll, dies wird jedoch nicht unmittelbar durchgeführt.

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 28. Mai 2013 12:48
von Abayo
Danke für die schnelle Antwort :)

Dann werd ich mir mal die genannten Klassen zu gemüte führen und einen direkten Aufruf für das PaintEvent testen (mal sehen ob es auf diesem Wege auch geht).

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 30. Mai 2013 13:13
von Abayo
Hi nochmal :)

Ich schaue mir gerade GraphicsView und GraphicsItem an und es sieht beides sehr interessant aus für mein Vorhaben. Da muss ich aber noch ein wenig weiterlesen :)

Was mich nun trotzdem noch bei oben genannten Fall interessieren würde:

Ist es möglich eine Zeichnung im PaintEvent der Basisklasse durchzuführen, welche dann als Hintergrund erscheint für die abgeleitete Klasse erscheint UND auf dem ich dann malen kann? (In diesem Fall: ein QImage reinkopieren und es dann drehen).
Ich habe irgendwie das Problem dass sobald das PaintEvent der abgeleiteten Klasse aufgerufen od. einfach nur initialisiert wird, wird mir der Hintergrund verdeckt. Ohne PaintEvent in der abgeleiteten Klasse (auch wenn keine Befehle drin sind) wird mir das in der Basisklasse gezeichnete Bild angezeigt.
Ich habe schon einen Ansatz versucht der den Hintergrund durchsichtig macht, aber das wird nur auf die abgeleitete Klasse ausgeführt und dann eben das bereits gezeichnete Bild auch durchsichtig.
Mit diesem Code habe ich das versucht (im Internet gefunden):

Code: Alles auswählen

setStyleSheet("background:transparent;");
setAttribute(Qt::WA_TranslucentBackground);
Um auf obige Frage zurückzukommen: Soll ich alles in einer Klasse im PaintEvent zeichnen, oder kann mien Ansatz auch funktionieren?

mfg,

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 2. Juni 2013 18:33
von Abayo
Da es immernoch zu dem Thema gehört mit dem dieser Thread getartet wurde frag ich nochmal hier:

Wenn ich nun versuchen möchte einen sauberen Code zu schreiben und mit der gegebenen Thematik (Basisklasse abgeleitete Klasse) sollte meine herangehensweise so aussehen dass ich:
1. Mit 2 Paintevents arbeite. Einmal in der Basisklasse und einmal in der davon abgeleiteten Klasse, oder
2. In der Basisklasse ein QImage und eine Paint-Mehtode vorbereite die ich in der abgeleiteten Klasse im PaintEvent nutze? (Also mit QPainter auf das vorbereitete QImage zeichnen und das damit veränderte QImage anzeigen)

Ich habe das Verfahren von Basisklasse und Vererbung einigermaßen begriffen, kämpfe aber noch mit der richtigen praktischen Einsatzweise.

Hoffe Ihr könnt mir hierbei weiterhelfen. (Was für Erfahrung Ihr mit diesem THema schon gemacht habt.)

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 2. Juni 2013 18:48
von veeman
Evtl. solltest du genauer Beschreiben was du vor hast bzw. was geschehen soll. Ich kann dir nicht ganz folgen.

Die paintEvent Methode ist virtuell (virtual), was bedeutet das; es bedeutet das bei jeder abgeleiteter Klasse die diese Funktion implementiert die Funktion der vorherigen "überschreibt".
Genauer bedeutet dies, das wenn diese Methode in der abgeleiteten Klasse implementiert ist die der Basisklasse nicht mehr aufgerufen wird.

Du hast jedoch die Möglichkeit in der Reimplementierten Funktion explizit die Funktion der Basisklasse aufzurufen.

Code: Alles auswählen

class Basis
{
     virtual void	paintEvent ( QPaintEvent * event )
     {
         // zeichne die Fläche weiß
     }

    void deinePaintMethode(QPainter &p)
    {
        // zeichne dein bild oder sonst was
    }
}

class KindA: public Basis
{
     virtual void	paintEvent ( QPaintEvent * event )
     {
         Basis::paintEvent(event); // explizieter aufruf, zeichne die Fläche weiß
         QPainter p(..);
         // zeichne was
         deinePaintMethode(p); // Zeichne das bild oder sonst was
         // zeichne noch was
     }
}

.....

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 3. Juni 2013 15:22
von Abayo
Hi Veeman

Wenn ich mich nicht verständlich ausgedrückt habe tut es mir leid, aber deine Erklärung hilft mir schonmal ein wenig.

Was ich genau Vorhabe:

In einem Grundfenster/Bildbereich/Display möchte ich eine GUI machen, indem ich mir Widgets/Anzeigeelemente erstelle mit denen ich mir Informationen anzeigen lassen kann.
Wenn nun mehrere Widgets/Anzeigeelemente fertig sind, sollen diese auf dem Anzeigebereich nach belieben oder nach Bedürfnis dargestellt werden, sich überlagern, sich verschieben, usw.. also miteinander interagieren.

Als Beispiel habe ich ja eine Ofenuhr oder eine Drehzahlanzeige genannt, welche dann solche Widgets/Anzeigeelemente wären. Bei der Drehzahl z.B. möchte ich einfach erstmal einen Kreis anzeigen in dem sich ein Zeiger dreht. Dieses Widget/Element möchte ich so aufbauen dass ich mit der Vererbung arbeite, da ich später spontan/dynamisch z.B. das Design verändern möchte (und die Datenkapselunf dabei ist).
Dabei soll die Basisklasse Base alles voreinstellen (Größe, Hintergrund, Position, Methoden auf die ich zurückgreifen kann) während dann die abgeleitete Klasse Erbe1 das optische Feintuning macht (Zeiger anzeigen, drehen lassen, Zahlen am Kreis anzeigen). In einer anderen abgeleiteten Klasse Erbe2 möchte ich dann statt dem Zeiger vielleicht eine Scheibe mit Zahlen wie bei einer Eieruhr in dem Kreis anzeigen und drehen lassen.

Ich dachte mir das sich dafür die Vererbung am ehesten eignet. Und da der Kreis von Base ja auch eine immer wieder vorkommendes Element von Erbe1 und Erbe2 ist habe ich nun versucht diese Aufgabe in die Basisklasse zu verlagern, da dass, nach meinem Verständnis, die Hauptaufgabe einer Basisklasse ist.
Die Verwendung mit der Vererbung ist mir laut Lehrbuch und Beispielen schon klar, nur hapert es an der praktischen Erfahrung vor allem in Bezug auf grafische Ausgaben.

Später tu ich das ganze Programm vielleicht auf ein Beagleboard oder ähnliches und versuch damit eine Maschine (keinen Ofen oder Auto^^) oder eine Motorsteuerung mit Rückmeldung der Motoren anzusteuern.

Ich hoffe nun ist Verständlich was ich damit Vorhabe :)

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 8. Juni 2013 15:31
von Abayo
Hallo allerseits :)

Ich versuche nochmal mein Glück mit vorhergehender Frage zur verwendung der Vererbung od. auch Polymorphie, was wäre bei meinem Thema besser:
1. Mit 2 Paintevents arbeite. Einmal in der Basisklasse und einmal in der davon abgeleiteten Klasse, oder
2. In der Basisklasse ein QImage und eine Paint-Mehtode vorbereite die ich in der abgeleiteten Klasse im PaintEvent nutze? (Also mit QPainter auf das vorbereitete QImage zeichnen und das damit veränderte QImage anzeigen)
Und ja, ich arbeite nebenbei auch schon mit den QGraphics-Architekturen, aber da kann ich ja auch Vererben.
Ich könnte auch anstelle von Vererbung (Basisklasse / abgeleitete Klasse) 2 einzelne Klasse mit QGraphicsObject (wg. TImer) machen und diese dann in der QGraphicsScene erstellen und eine klasse das Child der anderen Klasse machen (QGraphicsobject base(this); -> QGraphicsObject erbe(base); ).
Bin mir noch ned sicher was besser ist, blick da noch nicht so ganz durch.
Auch hierfür wäre ich für Anregungen dankbar!

So long,

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 9. Juni 2013 14:22
von veeman
Du hast doch schon sehr gute Ansätze, versuch diese einfach Umzusetzen.

Basisklasse
-> Zeichenmethoden definieren
-> Alle benötigten Zeichenobjekte anlegen

Kind:
-> Vorhande Zeichenobjekte anpassen
-> Zeichenmethoden aufruf
-> Ggf. weitere Sachen Zeichnen

Re: Malen mit 2 PaintEvent über abgeleitete Klasse

Verfasst: 9. Juni 2013 19:29
von Abayo
Danke für die Geduld soweit :)

Mit QPainter und QGraphicsView habe ich es hinbekommen XD


Eine Frage hätte ich noch was die Performance betrifft, da ich damit ja (noch) keine Erfahrung habe und aus den bisherigen Testprogrammen nichts erkennen kann:

Ist es besser ein QWidget als Grundfenster zu nehmen und mehrere andere QWidgets (mit Vererbung und Basisklasse, als fertiges graphisches Element) einzublenden und alle sich selber berechnen zu lassen.

ODER

Ein QGraphicsView mit einer Scene und mehreren QGraphicsObjects, wobei auch die Vererbung ähnlich wie beim Widget eingesetzt wird.

ODER

Ein QGraphicsView mit einer Scene und mehreren QGraphicsObjects, wobei so gut wie keine Vererbung verwendet wird. Stattdessen wird für jede Zeichenfunktion ein eigenes QGraphicsObject erstellt und diese verweisen dann aufeinander (QGraphicsobject kreis(this); -> QGraphicsObject zeiger(kreis); ).

WIe gesagt, ich bekomm alles hin kann aber nicht erkennen was besser wäre wenn ich dann mehrere verschiedene Anzeigen erstelle und anzeige. Und die Zeit um alles in drei ausführungen zu machen habe ich dann auch nicht.. WIll mich jetzt auf einen Weg festlegen um alles durchzuplanen und brauch eure Erfahrung dafür.

mfg,