Seite 1 von 1

QGraphicsView und QGraphicsScene

Verfasst: 6. September 2010 09:37
von QtNewbie
Hallo,

ich möchte in ein .jpg bild linien einzeichnen und diese am liebsten mit der maus verschieben. nachdem ich die examples durchstöbert hatte bin ich auf das graphicsview portedcanvas example gestoßen das diese funktionalität beinahe schon komplett zur verfügung stellt. mein Problem ist jetzt das ich später das bild auch komplett mit allen nicht rotierten und rotierten linien in einem .jpg wieder abspeichern will. bisher habe ich das immer mit qimage und qpainter mit qimage als painting device vom qpainter gemacht. wenn man dann die save funktion von qimage aufruft habe ich alles abgespeichert. mit dem qimage fällt mir die verschiebung aber sehr schwer, weshalb ich nun lieber auf qgraphicsview und qgraphicsscene umsteigen möchte, nur wie kann ich mit diesen klassen speichern eine art save funktion sehe ich in der doku nicht. gibt es einen anderen weg.
hier ist mein code bisher

Code: Alles auswählen

#include "graphics.h"

Graphics::Graphics(QWidget *parent, Qt::WFlags flags)
	: QWidget(parent, flags)
{
	QString path = "D:/Programmierung/C++/Graphics/trunk/Debug/SavePics/dfgd.jpg";
	ui.setupUi(this);
	m_qGraphicsScene = new QGraphicsScene();
	m_qGraphicsScene->addPixmap(QPixmap::fromImage(*(new QImage(path))));
	m_qGraphicsScene->addLine(0, 0, 768, 576, QPen( "red"));
	ui.graphicsView->setScene(m_qGraphicsScene);
}

Graphics::~Graphics()
{

}

void Graphics::on_pushButton_clicked()
{
	
}
wenn man sich das beispiel ansieht zeichnet er mir das bild und eine linie einmal diagonal durchs bild. wenn ich das linien malen aber vor das bild malen ziehe sieht man die linie nicht mehr. was mich erahnen lässt das linie und bild irgendwie getrennt werden. dieses problem hatte ich auch als ich erst nur mit qimage und nicht noch mit dem painter gearbeitet habe. was würdet ihr mir raten soll ich lieber mit graphicsview/scene weiterarbeiten was eigentlich mächtiger als image/painter ist oder soll ich wieder zum image/paitner zurück? wenn ich bei graphicsview/scene bleiben soll. wie würde das speichern dann funktionieren??

viele liebe grüße
newbie

Verfasst: 6. September 2010 09:57
von franzf
1) QGraphicsScene::render() zum Speichern. Code wie bisher, und anstatt dann selber auf dem painter zu malen einfach an render übergeben. Danach image.save() und fertig.
2) Zum Setzen von Ebenen brauchen die Items passende ZValues. Siehe Doku zu QGraphicsItem.

Für Interaktion mit dem User (wenn der mit der Maus die Linien verschieben können soll) ist eine grafische Präsentation unabdingbar. Graphics View macht das natürlich sehr einfach! Du kannst aber genauso nur von QWidget/QLabel ableiten, und mit eigenem Eventhandling (mousePress/mouseMove/mouseRelease/...) die Linien einfügen. Zum Verschieben einer bereits eingefügten Linie wirds natürlich schwerer, da die Linie kein grafisches Objekt ist wie bei GraphicsView, sondern nur ein Datenmember, der nicht direkt greifbar als Pixelansammlung auf dem Bildschirm liegt. Du musst also eigene Routinen anbieten, um bei einem click eine Linie zu suchen, finden (oder auch nicht), und dann verschieben zu können. Ist das zu kompliziert bleib bei Graphics View.

Verfasst: 6. September 2010 10:19
von QtNewbie
hi

super danke für die schnelle antwort.
kannst du den punkt 1 etwas genauer ausführen, ich versteh das nicht.
also ich male schon indirekt selbst mit dem painter, ich habe doch noch gar kein painter objekt erstellt
wie müsste die übergabe an den render aussehen?
Ich habe es so versuch das ich mir ein qImage erstellt habe und diesem dann eine aktuelle pixmap übergeben müsste. nur finde ich eine methode wie zum beispiel getPixmap() im qgraphicsscene nicht.

danke auf jeden fall

Verfasst: 6. September 2010 10:30
von franzf
QtNewbie hat geschrieben:kannst du den punkt 1 etwas genauer ausführen, ich versteh das nicht.
Ach komm... Da ist doch schon ein schönes Beispiel in der Doku zu render()...

Code: Alles auswählen

class Widget : public QWidget {
Q_OBJECT

QGraphicsScene* scene;

private SLOTS:
    void printToImage();

// usw.
};

void Widget::printToImage() {
    QImage img(500,300);
    QPainter p(&img);
    scene->render(&p);
    img.save(fileName);
}
Die scene wird natürlich VOR dem printToImage() gefüllt.

Verfasst: 6. September 2010 10:58
von QtNewbie
Hi

gut ich habs speichern geschafft. vielen dank für deine hilfe ich denke ich habs erstmal.

ps:
meintest du das beispiel?

Code: Alles auswählen

QGraphicsScene scene;
 scene.addItem(...
 ...
 QPrinter printer(QPrinter::HighResolution);
 printer.setPaperSize(QPrinter::A4);

 QPainter painter(&printer);
 scene.render(&painter);
mein problem lag hier daran das ich dachte ich müsste dem neuen qimage objekt was du da erstellt hast nicht nur size und format übergeben sondern irgendwie auch noch die aktuellen bilddaten. Also es ist jetzt schön das es läuft nur die kommunikation zwischen den klassen ist mir noch nicht so ganz klar.
ist es so das wenn ich dem render(&painter) den painter als referenz übergebe der compiler alles was im graphicsscene objekt steht in den painter schreibt und weil das painting device vom painter ein qimage ist, der ganze kram dann auch im qimage steht und ich schlussendlich davon die save methode dann aufrufen kann?

liebe grüße
und danke für die viele hilfe
newbie

Verfasst: 6. September 2010 12:01
von franzf
QtNewbie hat geschrieben:ist es so das wenn ich dem render(&painter) den painter als referenz übergebe der compiler alles was im graphicsscene objekt steht in den painter schreibt und weil das painting device vom painter ein qimage ist, der ganze kram dann auch im qimage steht und ich schlussendlich davon die save methode dann aufrufen kann?
Der Compiler schreibt gar nix! Die Aufrufe passieren dann zur Laufzeit (gelinkt ist das Programm ja hoffentlich korrekt :P).
QImage ist ein QPaintDevice. Dafür muss eine passende QPaintEngine geschrieben werden, die viele viele virtuelle Methoden hat, die alle implementiert werden müssen. Ein QPainter verwendet die paintEngine um zu zeichnen (es werden eben jene implementierten Methoden verwendet). "Der ganze Kram" steht dann im QImage, wenn ein Painter das da reingezeichnet hat. Da der Compiler nicht wissen kann, was das für ein Kram im Endeffekt ist kann der da noch gar nix machen!