SVG Umrandung in QT4?

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

SVG Umrandung in QT4?

Beitrag von nibbel »

Hallo, ist es möglich ein Objekt vom Typ QGraphicsSvgItem direkt mit einer Umrandung zu versehen, zb wenn ich es anklicke (markiere)?

Bsp:

Code: Alles auswählen

QGraphicsSvgItem *stern=new QGraphicsSvgItem("stern.svg");

scene->addItem(stern);

stern->setFlags(QGraphicsItem::ItemIsMovable);

//wenn stern angeklickt
//setze rand drum
//wenn nicht
//kein rand
Gibt es für sowas schon eine Methode?
Oder müsste ich das selbst schreiben`?
Zb mit einem Painter selber drum malen.

Ich wollte erst fragen, da es ja zb für das bewegen durch mausklicken und bewegen ja auch schon eine schöne Methode gibt.


*edit
Weis denn da keiner Abhilfe?

Mit dem painter habe ich es schon versucht, nur leider funzt der nicht mit svg grafiken.
Sephral
Beiträge: 201
Registriert: 1. Februar 2006 09:40
Kontaktdaten:

Beitrag von Sephral »

Hallo,
ich habe vor eine Weile vor dem selben Problem gestanden.

Ich hatte versucht selbst den Rahmen zu zeichnen (paint event), das klappte bei mir aber nicht, da der Inhalt des Widgets durch eine Video-API bearbeitet wurde (wurde ständig drüber gezeichnet und die Performance war auch schlecht).

Ich habe mich am Ende für eine ganz simple Lösung entschieden:
Ich habe alle Elemente, die ich umrahmen wollte, in einen QFrame gepackt. Im Frame war dann meine Anzeige-Widget (Box-Layout) und das Frame hatte einen margin von 2-3 Pixeln.

Beim Click-Event färbe ich nun einfach den Hintergrund des Frames ein, dadurch ergibt sich um das Anzeigeelement ein kleiner Rahmen. Sobald auf ein anderes Element geklickt wird, setze ich die Hintergrundfarbe des zuletzt angeklickten einfach wieder um.

Ciao,
Sephral
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Schreib dir eine Klasse, die von GRaphicsSvgItem erbt. Dann überschreibst du die paint-Methode:

Code: Alles auswählen

void Item::paint( QPainter* p, ... )
{
    QGraphicsSvgItem::paint( p, ... );
    p->drawRect( boundingRect() );
}
Das sollte so gehen ;)

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

Beitrag von nibbel »

hmm danke erstmal, aber irgendwie steh ich nun aufem schlauch.
In C++ hab ich noch nie eigene Klassen geschrieben, erst recht nicht von anderen geerbt.
Aber ich kenne das aus Java, also hab ich kurz im netz geschaut und gleich rausgefunden wie man das macht.

Hab dann schnell eine klasse namen SVGClass erstellt und ihr den namen SVGClass.cpp gegeben.

Code: Alles auswählen

#include <QPainter>

class SVGClass : public QGraphicsSvgItem {
	
	String svgfile;
	

	void Item::paint( QPainter* p, svgfile)
	{
	    QGraphicsSvgItem::paint( p, svgfile);
	    p->drawRect( boundingRect() );
	}

}
Das wollte ich dann in der Ablaufklasse erzeugen:

Code: Alles auswählen

#include <SVGClass>

.....
   
   SVGClass svg;
Einen Konstruktor habe ich wie ihr seht vorerst nicht gemacht, wollte halt nur mal kurz testen ob meine Klasse so überhaupt erkannt wird.

Aber irgendwie nicht..

er meint immer ich hätte svg nich deklariert...

Kann mir einer kurz helfen?

danke

ach noch was, hab ich einen fehler in der Klasse?
Irgendwie zeigt mir Eclipse in dieser Klasse keine Fehler an, habs vorhin mal versucht mit einem falsch geschriebenen void, aber nichts...
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

In C++ hab ich noch nie eigene Klassen geschrieben, erst recht nicht von anderen geerbt.
Glaub ich nicht...

QGraphicsSvgItem hast du aber schon includiert?

Außerdem wäre die richtige Fehlermeldung nicht schlecht, deine ergibt keinen Sinn...
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

sorry, mein problem entstand dadurch, das ich kein .h datei hatte.

Nachdem ich mir ein tutorial mal genauer durchgelesen habe, fand ich den fehler. Hab mir nun noch mal eine erläuterung dazu durchgelesen..
Nunja dieses Modulkonzept kenn ich aus Java nunmal nicht.

Endlich hab ich dadurch auch ungefähr gechekt wofür das :: steht (namespace).

Das einzige was ich nun noch wissen müsste, ist der aufbau dieses Teiels.

Code: Alles auswählen

	void Item::paint( QPainter* p, svgfile)
	{
	    QGraphicsSvgItem::paint( p, svgfile);
	    p->drawRect( boundingRect() );
	}
Also Item ist ein namespace und darin ist die funktion paint drin richtig?
dann muss man noch die übergabe parameter eintragen. Einmal ein objekt vom typ qpainter und einmal eine stringvariable, ist das soweit richti?

dann wird der teil überschrieben ?!?!
QGraphicsSvgItem::paint( p, svgfile);
Wieder ein namespace mit der funktion paint und ich übergebe das erzeugte objekt und die stringvariable
p->drawRect( boundingRect() );
an dieser stelle sage ich ihm er soll bei objekt p ein rechteck, über die werte die boundingRect() ermittelt, zeichnen.

Ist das soweit richtig?

wie gestalte ich den korrekten aufruf in der main methode?

ich kenn das bisher nur in der form

objekt.methode
oder class.methode...

aber das geht hier ja nicht.

dazu soll das ja nur ausgeführt werden, wenn man die SVG anklickt.

ginge dazu dieser codeschnippsel:

Code: Alles auswählen

if (kreis->isSelected()) {
			svg...
     	 }
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Code: Alles auswählen

#include <QPainter>
#include <QGraphicsSvgItem>

class SVGClass : public QGraphicsSvgItem {

public:   
  SVGClass(const QString &fileName, QGraphicsItem *parent=0) :
    QGraphicsSvgItem(fileName, parent) {};

  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0)     
   {
       QGraphicsSvgItem::paint(painter, option, widget);
       if (isSelected()) {
         painter->drawRect(boundingRect());
       }
   }
};
Mal davon abgesehen, daß normalerweise wenn das ItemIsSelectable-Flag gesetzt ist, auch ein Rahmen gezeichnet wird.
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

nun verstehe ich aber immer noch nicht wie ich den aufruf in der mainmethode gestalten muss.
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

nungut

ich hab ein objekt davon erstellt mit dem befehl:

Code: Alles auswählen

SVGClass *svg();
Ist ja toll, nun hab ich ein objekt namens svg von der klasse SVGClass.

ABer das bringt mir rein garnichts weil ich nicht weis wie ich ihm nun in der main methode sagen soll, wenn eines meiner svgitems angeklickt wird, soll er die klasse ausführen.

auch ein einfaches
macht in meinen augen keinen sinn, da ja nicht übergeben wird.. also das richtige svgitem objekt....

Kann mir nun bitte einer weiter helfen?

ich komme alleine einfach nciht weiter.....
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Wie wärs wenn du die mal ein paar C++-Grundlagen anschaust?

Code: Alles auswählen

#include <QtGui>

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

  QSVGClass *svg=new QSVGClass();
  scene->addItem(svg);

  app.exec();
}
ungetestet...
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

Da hattest du recht, ich hab mir nun nochmal was von meinem Ausbilder erklären lassen. Dadurch hab ich das nun selber hinbekommen.

Mein zweites Problem ist, das ich nicht sehr gut englisch kann und somit immer wieder probs in der doku habe. Noch dazu kommt, das ich das mit den Pointern noch nicht so ganz gecheckt habe wie auch das mit den Namespaces.

Aber ich hab es soweit hinbekommen.

Nur eins klappt noch nicht ganz.

Code: Alles auswählen

painter->drawRect(boundingRect());
das macht mir ein schönes rechteck, aber nicht um mein svgClass objekt sondern einfach ganz links oben in das view.

Und dann noch

Code: Alles auswählen

if (isSelected()) 
ist doch eingendlich dazu da, um zu ermitteln, ob das objekt angeklickt wurde oder?

dann passiert aber nichts, dabei bräuchte ich sowas um das rechteck beim woanders hinklicken wieder weg zu zeichnen (sprich else..)

mich würde auch mal interessieren, wo ihr nach den funktionen so sucht, wenn ihr eine braucht wo ihr nicht wisst ob es das gibt?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

mich würde auch mal interessieren, wo ihr nach den funktionen so sucht, wenn ihr eine braucht wo ihr nicht wisst ob es das gibt?
In der Doku, wo sonst?

isSelected funktioniert natürlich nur, wenn das Item das ItemIsSelectable-Flag hat. Du könntest natürlich noch hasFocus verwenden, da immer nur ein Item den Focus haben kann, aber dann mußt erst das ItemIsFocusable-Flag setzen.
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

dann werde ich mich bemühen etwas mehr mit der docu zurecht zu kommen.

*edit:
Das ja klasse, hab durch die doku endlich mal gecheckt wie das mit den Flags funzt.

Aber eine sache finde ich in der doku einfach nicht...

Ich suche eine möglichkeit mit der ich das rechteck direkt um das item zeichne.
Momentan lasse ich ihn einfach, wenn das Item selected wird das hier ausführen:

Code: Alles auswählen

painter->drawRect(boundingRect());
Leider zeichnet er mir dann das rechteck in den richtigen maßen ganz an den anfang des view, sprich links oben im fenster.

Ich werde es weiter mit der doku versuchen, aber vieleicht hat einer einen Tipp für mich

*edit2
Hab nun rausgefunden, das ich das drawrect auch per (x,y,high,width) ansprechen kann.

Hab auch schon rausgefunden das ich per x() und y() die ersten beiden werte vom svgitem bekommen kann. Aber die anderen beiden werte muss ich noch finden

*edit3
da meien items eh immer 64x 64 sind habe ich das vorerst mal manuel übergeben, aber mir wäre es doch lieber wenn es über eine methode ginge.

Noch dazu habe ich ein etwa größeres problem, was ich nicht verstehe.

Er zeichnet mir jetzt mein rechteck auch in der richtigen größe, das interesannte ist nur.
Das SVGItem meint, das der Punkt 0,0 für ihn genau in der mitte des fensters ist, das ist aber nicht richtig.

Das rechteck machts hingegen richtig, es positioniert sich direkt oben links bei 0,0.

Cool ist auch noch, das wenn ich das SVGItem bewege, sich auch das rechteck bewegt, nur leider halt an der falschen stelle.
Weil halt beide an der falschen stelle sind...

Kann mir einer sagen woran das liegt?
hier noch ein bild, damit ihr wisst was ich meine:

Bild
nibbel
Beiträge: 35
Registriert: 9. Mai 2007 10:30

Beitrag von nibbel »

So ich weis nun das es daran liegt, das das view globale daten verwendet und die scene locale daten.

Das Problem ist nun, ich weis nicht wie ich das ändern kann.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ändern nicht, aber du kannst es mit den mapTo... Methoden umrechnen lassen
Antworten