Seite 1 von 1

[Qt4] Drucken und eigene Paintengine - das gleiche Problem

Verfasst: 26. Juli 2006 20:04
von Morgoth
Nabend zusammen!

Ich schreibe als Studienarbeit ein Programm zur grafischen Darstellung von Messdaten. Mein Prof möchte dabei unbedingt eine WMF-Ausgabe realisiert bekommen, "muss doch gehen, ein Kommilitone von Ihnen hat das doch auch geschafft" (der hat aber nur Windows als Zielplattform, ich wollte unabhängig werden, das hab ich jetzt davon ;) ). Über den Sinn kann man natürlich streiten, das lassen wir aber lieber mal. Drucken soll natürlich auch gehen.

Also habe ich ein Widget geschrieben, in dem geplottet wird, und dieses möchte ich also sowohl gedruckt als auch nach WMF exportiert haben.

In dieses Widget wird in mehreren Funktionen gezeichnet, die alle über paintEvent() aufgerufen werden. Meine Idee war nun, eine Membervariable QPaintDevice *pd für das Widget zu implementieren, die dann, wenn ich drucken will, einmalig geändert wird (auf ein QPrinter), dann wird gezeichnet, und wieder das Widget als QPaintDevice benutzt.

Natürlich funktioniert es nicht (würde ich sonst fragen?).

Genau das gleiche Problem habe ich beim WMF-Export. Dafür habe ich mir in Ermangelung einer für Qt4 vorhandenen Lösung eine eigene PaintEngine geschrieben, die auch funktioniert (ok, bisher nur Linien und Rechtecke, aber das Prinzip haut hin). Getestet habe ich das so:

Code: Alles auswählen

QWMF* pd=new QWMF(fileName, plotWidget);
QPainter p(pd);
p.drawRect(10, 10, 50, 50);
p.drawLine(0, 0, 100, 100);
p.end();
QWMF ist das PaintDevice, das die neue PaintEngine benutzt, plotWidget ist ein Zeiger auf das eigentliche Widget, das benutze ich da zur Sammlung metrischer Informationen.

Ergebnis ist ein wunderbar skalierbares Bild, das sich völlig problemlos in z. B. MS Word einbinden lässt.

Nur wenn ich die - ganz offensichtlich falsche - Vorgehensweise vom Drucken darauf verwende, tut sich nichts - fast nichts. Es wird eine korrekte WMF-Datei mit Header und Tail (2 Bytes mit dem Wert 0 :rolleyes ) erstellt, was bedeutet, dass QWMFEngine::begin() und QWMFEngine::end() aufgerufen werden, denn darin werden diese Daten in die die Datei geschrieben.

Vielleicht bin ich auch nur zu doof, und hab das Prinzip von Qts Arthur nicht verstanden, jedenfalls habe ich im Netz keine Lösung für mein Druckproblem gefunden (Notiz für mich: mal vorhandenen Quellcode von anderen Programmen durchsuchen), also einfach den Zeichenfunktionen des Widgets ein anderes Paintdevice unterjubeln.

Vielleicht habt Ihr ja eine Idee, oder vorhandene Lösung.

Gruß
Morgoth

Verfasst: 27. Juli 2006 11:20
von Morgoth
Ich hab den Fehler gefunden: erst richtig lesen, dann denken, dann coden.

Wenn ein QPainter mit

Code: Alles auswählen

QPainter p(paintdevice);
erzeugt wird, ruft dieser automatisch QPaintEngine::begin() auf. Ebenso, wenn dieser QPainter vernichtet wird, ruft er QPaintEngine::end() auf. Es ist dann natürlich mehr als unglücklich, in einer eigenen QPaintEngine so wichtige Sachen wie Initialisierung der Datei (*.wmf, zur Erinnerung) und verschiedener Variablen sowie abschließendes Schreiben in begin() und end() zu packen und gleichzeitig das Zeichnen auf mehrere Funktionen aufzuteilen und in jeder Funktion einen neuen QPainter zu benutzen.

Nun gibt es zwei Lösungen:

- man packt den Code aus begin() und end() in CTor und DTor

- man benutzt einen einzigen QPainter für die Widgetklasse

Ersteres habe ich jetzt testweise in meiner QWMFEngine getan, letzteres ist wahrscheinlich die elegantere Methode, vor allem weil ich vermute, dass meine Druckversuche genau an dem gleichen Verhalten scheiterten. Das werde ich jetzt bei Gelegenheit testen.

Gruß
Morgoth