Ein SVG Bild innerhalb eines GraphicsView per maus bewegen

Alles rund um die Programmierung mit Qt
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Ein SVG Bild innerhalb eines GraphicsView per maus bewegen

Beitrag von nibbel »

Hallo,
ich habe ein SVG Bild mit qpaint erstellt, das in ein qpicture gehauen und das dann wiederrum in ein qlabel gelegt um das dann auf dem qwidget anzeigen zu lassen.

(Es geht bestimmt einfacher aber das ist mein erstes Qt Projekt und somit hoffe ich das jemand mir sagt wie es einfacher geht.)

Nun hab ich noch ein GraphicsView in meinem Qwidget liegen.
Das Qlabel lasse ich genau da drüber anzeigen. (Gibts ne möglichkeit das wirklich ins QGraphicsView zu legen?)

Also ich will nun das ich das label mit maus anklicken kann und dieses dann innerhalb des QGrahpicsView einfach fröhlich herum zu schieben ist.
Ne art drag and drop in einem fenster^^.

wer noch den code sehen will hier:

Code: Alles auswählen

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QWidget window; 
        
        QGraphicsView *graphicsview = new QGraphicsView(&window);
        graphicsview->setGeometry(QRect(10, 10, 620, 460)); 
        
         QPicture picture;
         QPainter painter;
         painter.begin(&picture);           // paint in picture
         painter.drawEllipse(300,200, 80,70); // draw an ellipse
         painter.end();                     // painting done
         picture.save("drawing.pic");       // save picture
        
         QPicture picture2;
         picture2.load("drawing.pic");           // load picture
         QPainter painter2;
         painter2.begin(&window);              // paint in myWidget
         painter2.drawPicture(300, 200, picture2);    // draw the picture at (0,0)
         painter2.end();                         // painting done   

         QLabel *label=new QLabel(0, &window);
   		 label->setGeometry(220,140, 101, 101);
   		 label->setPicture(picture2);

		 
         window.setFixedSize(640,480);
         window.show();
         return app.exec();
    }
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Code: Alles auswählen

void QGraphicsItem::setFlags ( GraphicsItemFlags flags )
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

Es wäre echt nett, wenn du mit ein Paar mehr informationen rausrückst.

Ich denke (ich hab das in qt noch nie gemacht), das dies der Kopf einer Funktion ist (eventuell auch methode).
Nur leider habe ich nicht den ansatz einer Idee wie ich das genau verstehen soll.
Auch nicht wie ich mit dem eigendlichen Code "des bewegens" anfangen kann.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Hast du die Dokumentation zu dieser Funktion durchgelesen?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Jetzt seh ich es erst, warum verwendest du QGraphicsView, aber kein QGraphicsScene und keine QGraphicsItems?
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

ich bekomme es einfach nicht hin in das graphicsitem eine svg datei zu binden.

Bzw ein svg bildchen in dem graphicsitem zu erstellen. (bessere variante)


Ich weiß auch nicht. Scheine heute auf dem schlauch zu stehen.
In Java mit swing hatte ich nie solche probs..

Vieleicht kannst du mir ja weiter helfen.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Code: Alles auswählen

int main(int argc, const char *argv[]) {
  QApplication app(argc, argv);

  QGraphicsScene *scene=new QGraphicsScene();
  QGraphicsView *view=new QGraphicsView();
  view->show();
  view->setScene(scene);

  QGraphicsSvgItem *item=new QGraphicsSvgItem("/mein/item.svg");
  scene->addItem(item);
  item->setFlags(QGraphicsItem::ItemIsMovable);

  return app.exec();
}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

QGraphicsSvgItem
GraphicsFramework -> drag and drop
Lies es bitte GENAU, da steht alles drinnen was du wissen solltest...

// edit:
zu spät, upsala war schneller und netter :)
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

^^
Das ist mal ein luxus, bekomm ich gleich die ganze antwort.
Ich danke erstmal dafür.
Aber ich habe mir trotzdem die ganzen Sachen dazu (doku von trolltech) angeschaut.
Ein Problem hab ich aber noch.
Zum Verständnis, ich arbeite mit Eclipse unter Windows (gibt es was besseres?)

Also mir wird gesagt das QGraphicsSvgItem nicht definiert ist, aber ich habe ein include dafür gesetzt (sogar mal wegen rechtschreibfehler aus der Doku kopiert).
Auch habe ich nochmal in den Optionen meines Projektordners einen externen include Ordner aus dem QT verzeichnis gesetzt (Qt/include/QSVG Ordner)
In diesem Ordner gibt es auch eine 1Kb große QGraphicsSvgItem Datei


*edit:

Oder kann es sein das ich einen fehler beim erstellen meiner SVG habe?

Code: Alles auswählen

  QPicture picture;
  QPainter painter;
  painter.begin(&picture);           // paint in picture
  painter.drawEllipse(0,0, 80,70); // draw an ellipse
  painter.end();                     // painting done
  picture.save("drawing.svg");       // save picture

  QGraphicsSvgItem *item=new QGraphicsSvgItem("drawing.svg");
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

nibbel hat geschrieben:*edit:

Oder kann es sein das ich einen fehler beim erstellen meiner SVG habe?

Code: Alles auswählen

  QPicture picture;
  QPainter painter;
  painter.begin(&picture);           // paint in picture
  painter.drawEllipse(0,0, 80,70); // draw an ellipse
  painter.end();                     // painting done
  picture.save("drawing.svg");       // save picture

  QGraphicsSvgItem *item=new QGraphicsSvgItem("drawing.svg");
Das stellt durchaus ein Problem dar, denn das Format, in dem ein QPicture abgespeichert wird, ist proprietär binär:
Doku hat geschrieben:A picture serializes painter commands to an IO device in a platform-independent format. They are sometimes referred to as meta-files.
Qt pictures use a proprietary binary format. Unlike native picture (meta-file) formats on many window systems, Qt pictures have no limitations regarding their contents. Everything that can be painted on a widget or pixmap (e.g., fonts, pixmaps, regions, transformed graphics, etc.) can also be stored in a picture.
SVGs generieren (also das xml-basierte Format) ist (wenn ich das recht verstehe) ein neues Feature von Qt-4.3. Auf die Schnelle bin ich da noch nicht so durchgestiegen, aber mal schaun ;)

Ja, hier:
QSvgGenerator ist das was du suchst. Ist ein QPaintDevice, auf welches du QPainter los lassen kannst. Same as QPicture, mit setFileName() kannst du den Dateinamen angeben.

Grüße
Franz

// edit
JAAA :D

Code: Alles auswählen

#include <QGraphicsScene>
#include <QApplication>
#include <QGraphicsView>
#include <QSvgGenerator>
#include <QPainter>
#include <QGraphicsSvgItem>


int main(int argc, char **argv) {
   QApplication app(argc, argv); 
 
   QGraphicsScene *scene=new QGraphicsScene(); 
   QGraphicsView *view=new QGraphicsView(); 
   view->show(); 
   view->setScene(scene);

	QSvgGenerator picture;
	picture.setFileName( "drawing.svg" );
   QPainter painter; 
   painter.begin(&picture);           // paint in picture 
   painter.drawEllipse(0,0, 80,70); // draw an ellipse 
   painter.end();                     // painting done
	
   QGraphicsSvgItem *item=new QGraphicsSvgItem("drawing.svg");
   scene->addItem(item); 
   item->setFlags(QGraphicsItem::ItemIsMovable); 
 
   return app.exec(); 
}
Und nicht vergessen, in deinem *.pro-file den Eintrag QT += svg hinzuzufügen.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Aber jetzt noch was anderes:
Für was brauchst du denn überhaupt ein QGraphicsSvgItem, wenn du das SVG-File erst im Programm erstellst? Schreib dir doch eine eigene Klasse, die du von QGraphicsItem ableitest. Dann nur noch schnell

Code: Alles auswählen

QRectF QGraphicsItem::boundingRect () const;
void QGraphicsItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 );
überschreiben, und schon hast du ein für deine Zwecke passendes QGraphicsItem.

Oder war das nur zu Demo/Test-Zwecken? Dann kannst du das oben wieder vergessen (oder für spätere Anwendungen merken ;))
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

Danke für die Hilfe.
Und jaein es ist schon zu testzwecken, ich brauche es aber später auch effektiv. Wie du das mit dem Überschreiben meinst, weis ich auch noch nicht genau.


Und zu meinem Prob, ich galube dir das es damit geht.
Nur leider hänge ich noch einen Fehlerpunkt dahinter fest.

Mein Eclpise findet anscheinend die Klasse #include <QGraphicsSvgItem>
nicht.
Denn das wird mir rot unterstrichen (QSvgGenerator auch).

Obwohl ich den path für die externen includes eingerichtet habe.

Weist du vieleicht woran das liegen kann?

*edit:
Auch wenn ich deinen Code direkt übernehme wird mir:

Code: Alles auswählen

#include <QSvgGenerator>
#include <QGraphicsSvgItem>

   QSvgGenerator picture;
   picture.setFileName( "drawing.svg" );

   QGraphicsSvgItem *item=new QGraphicsSvgItem("drawing.svg");
   
   item->setFlags(QGraphicsItem::ItemIsMovable);
Rot unterstrichen.
Ich bin mir sicher er findet die klassen einfach nicht.
Nur weis ich nicht wie ich das beheben kann.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Eclipse arbeitet doch auch mit qmake resp. dem qt-pro(ject)-file. In diesem solltest du eintragen QT += svg.
Da ich selbst unter Linux mit kdevelop (für kleine Sachen auch gerne kate) arbeite, und eclipse in frühen Tagen zur Java-Programmierung angetestet habe (und sofort wieder verworfen :D), kann ich da aber leider nicht mehr sagen.

Ansonsten gibt es (plattformübergreifend) noch: Ich denke bei den links findest du sicher etwas, was dir zusagt.

Grüße
Franz
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

Danke dir, aber leider muss ich den Eclispe verwenden, da ich im voranlaufenden auch cvs und svn benutzen muss und das unterstützen die anderen alle nicht.
Eine möglichkeit wäre noch visual studio, aber das kostet nunmal geld...


Ich werde wohl solange suchen müssen, bis das problem gelöst ist.
Aber sobald ich es gefunden habe, werde ich es hier nochmal angeben.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Wegen dem QGraphicsItem ableten, hier ein kleines Beispiel:

staritem.h

Code: Alles auswählen

#ifndef _STAR_ITEM_
#define _STAR_ITEM_

#include <QGraphicsItem>

class QRectF;


class StarItem : public QGraphicsItem
{
	public:
		StarItem( QGraphicsItem *parent = 0 ) : QGraphicsItem(parent) {}

                // die beiden hier musst du implementieren
                // um ein "gültiges" QGraphicsItem zu erhalten
		void paint( QPainter *, const QStyleOptionGraphicsItem *, QWidget *widget=0 );
		QRectF boundingRect() const;
};

#endif  // _STAR_ITEM_
staritem.cpp

Code: Alles auswählen

#include "staritem.h"

#include <QPainterPath>
#include <QPainter>
#include <QLinearGradient>
#include <QRectF>

#include <math.h>


const float Pi = 3.14159f;

void StarItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
	Q_UNUSED( option );
	Q_UNUSED( widget );
	
	QPainterPath starPath;
	starPath.moveTo( 100, 50 );
	for (int i = 1; i < 5; ++i) {
		starPath.lineTo( 50 + 50 * cos(0.8 * i * Pi),
							  50 + 50 * sin(0.8 * i * Pi) );
	}
	starPath.closeSubpath();

	QLinearGradient gradient(0, 0, 0, 100);
	gradient.setColorAt(0.0, Qt::red);
	gradient.setColorAt(1.0, Qt::yellow);
	painter->setBrush(gradient);
	painter->setRenderHint( QPainter::Antialiasing, true );
	painter->drawPath( starPath );
}

QRectF StarItem::boundingRect() const
{
	return QRectF( 0, 0, 100, 100 );
}
main.cpp

Code: Alles auswählen

#include "staritem.h"

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QApplication>


int main(int argc, char **argv)
{
	QApplication app(argc, argv);
	
	QGraphicsScene *scene=new QGraphicsScene();
	QGraphicsView *view=new QGraphicsView();
	view->setScene(scene);
	
	StarItem *item = new StarItem;
	item->setFlags(QGraphicsItem::ItemIsMovable);
	scene->addItem(item);

	view->show();

	return app.exec();
}
Viel Spaß damit :)

Grüße
Franz
Antworten