Seite 1 von 1

QGraphicsView - Aufbau/Items verschieben/Signale

Verfasst: 14. Juni 2009 22:34
von marcwa
Hallo zusammen,

ich hab noch ein paar Grundlagen/Aufbau-Probleme und hoffe ihr könnt mir da weiter helfen :) (bin noch nicht sehr Qt versiert..)
Also prinzipiell will ich GraphicItems per Maus verschieben und an einem späterem Raster "andocken" können, also wenn das Item im 10px Bereich zum Raster ist, soll es in das Raster springen.

Dafür habe ich folgendes gemacht:

in der main eine Instanz meines EllipseItems der scene hinzugefügt,
in dem move-Event des EllipseItems (s.u.) soll das Signal itemMoved von mir ausgelöst werden und das wollte ich wiederum in der main dann später mit der Funktion zum "andocken" verbunden werden (provisorisch ist jetzt erstmal das quit drin)

Code: Alles auswählen

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene;
    scene.setSceneRect(-100.0 , -100.0 , 600.0,600.0);

    MyQGraphicsEllipseItem *item = new MyQGraphicsEllipseItem(0, &scene);
    item->setRect(-50.0,-50.0,100.0,100.0);
	item->setFlag( QGraphicsItem::ItemIsMovable );
	
    QGraphicsView view(&scene);
    view.setRenderHint( QPainter::Antialiasing);
    view.show();

    //connect(item, SIGNAL(itemMoved()), a, SLOT(quit()));
    return a.exec();
}
mein ellipseitem

Code: Alles auswählen

#include <QGraphicsEllipseItem>
#include <QObject>

class MyQGraphicsEllipseItem : public QGraphicsEllipseItem
{

public:
    MyQGraphicsEllipseItem(QGraphicsEllipseItem *parent, QGraphicsScene  *scene) :
            QGraphicsEllipseItem(parent, scene){}
protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
signals:
    void itemMoved();

};
#endif // MYQGRAPHICSELLIPSEITEM_H

Code: Alles auswählen

#include <QMouseEvent>

void MyQGraphicsEllipseItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    setCursor(Qt::OpenHandCursor);
    QGraphicsEllipseItem::mouseMoveEvent(event);
	emit itemMoved();
}

Soweit zum aktuellen Stand, jetzt zu meinem Problem :D

wenn ich jetzt versuche in der main das signal meines Ellipseitems zu verbinden, bekomme ich die Fehlermeldung, dass connect in diesem Gültigkeitsbereich nicht definiert wurde.
Muss ich die main jetzt irgendwie von QWidget erben lassen? oder ist der ganze Aufbau evtl schon Nachteilhaft?

Hoffe Ihr könnt mir was weiterhelfen

MfG Marc

Verfasst: 14. Juni 2009 22:45
von franzf
Oioioi ;)
Die main kann nicht von irgend etwas erben. Die ist so definiert und wird gebraucht als fester Einsprungpunkt wenn du dein Programm starten willst.

Und "connect" in einer freien Funktion bzw. in einer Non-QObject-Memberfunktion geht nicht ;)
Zum Glück gibt es connect auch als static-Funktion
-> ersetze connect durch QObject::connect.

Aber für deinen Fall wäre es besser wenn du eine eigene Klasse von QGraphicsScene ableitest. Stell dir vor, du musst für jedes eigene GraphicsItem eine eigene Implementierung abliefern. Oder erst ein eigenes Item implementieren und alle eigenen Items davon erben lassen. Dann bleibt deine "Raster"-Funktionalität aber außen vor für die Qt4-Standard-GraphicsItem, z.B. QGraphicsRectItem oder auch QGraphicsWidget.

Außerdem such mal hier im Forum, da gab es schon (mindestens 1x) so eine Frage wegen Raster in nem GraphicsView.

Grüße
Franz

Verfasst: 15. Juni 2009 00:04
von marcwa
Hi Franz,
das QObject::connect scheint zu funktionieren, allerdings bekomme ich jetzt die viel-sagende Meldung "collect2: ld gab 1 als Ende-Status zurück".

Ich glaube das bezieht sich auf "emit itemMoved();" in der MyEllipseItem.

Damit meine Klasse Signale und Slots benutzen kann, muss sie ja von QObject abgeleitet sein; erbt QGraphicsItem nicht von QObject? Wie wäre das dann hier möglich? von QGraphicsEllipseItem und QObject erben? (kling nicht so wunderschön)

Die QGraphicsScene scheint ja von QObject zu erben, also sollte ich ja da dieses Problem nicht haben, nehme ich mal an (bzw werde ich nachher mal ausprobieren).
Und wenn ich von QObject erben lasse, muss dann immer das Makro Q_OBJECT gesetzt werden?

Oder hängt die "collect2"-Fehlermeldung mit was ganz Anderem zusammen?

Verfasst: 15. Juni 2009 07:44
von franzf
marcwa hat geschrieben:Hi Franz,
das QObject::connect scheint zu funktionieren, allerdings bekomme ich jetzt die viel-sagende Meldung "collect2: ld gab 1 als Ende-Status zurück".
Zeig bitte die ganze Meldung. Das ist nur das Resultat, wir brauchen die Ursache :P
Damit meine Klasse Signale und Slots benutzen kann, muss sie ja von QObject abgeleitet sein; erbt QGraphicsItem nicht von QObject? Wie wäre das dann hier möglich? von QGraphicsEllipseItem und QObject erben? (kling nicht so wunderschön)
Multiple inheritance.

Code: Alles auswählen

class EllipseItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
    ...
};
Aber geht nur, wenn du als erste Klasse QObject schreibst, sonst gibts Probleme.
Die QGraphicsScene scheint ja von QObject zu erben, also sollte ich ja da dieses Problem nicht haben, nehme ich mal an (bzw werde ich nachher mal ausprobieren).
Schau dir mal noch an, was ich sonst noch über die Vorteile einer Raster-Implementierung via QGraphicsScene (kannste aber auch via QGraphicsView machen...) geschrieben hab.
Bei nem Drag kannst du dies in mouseMoveEvent() bearbeiten, und dein Item einfach nur dann weiter rücken, wenn du (nahe genug) am nächsten Rasterpunkt bist (QGraphicsItem::setPos()).

Verfasst: 15. Juni 2009 14:52
von marcwa
So, hab das jetzt alles via QGraphicsScene gelöst und funktioniert soweit auch schon ganz gut. (somit entfallen auch die vorherigen Probleme, danke dafür schonmal :D )
Wegen der Raster-Funktion habe ich jetzt noch was um gedacht, und versuche als Raster andere GraphicItems zu benutzen.

Deswegen hätte ich dann nochmal folgende Frage:
Das Item auf das geklickt wurde bekomme ich mit itemAt, ist es mir jetzt noch möglich zu überprüfen auf was für ein GraphicItem ich geklickt habe?

Also ich speichere den Zeiger des Items in (der Membervariable meiner Scene) QGraphicsItem *selectedItem;
Allerdings brauch ich den Zeiger nur, wenn es sich um ein PixmapItem handelt, kann ich den Zeiger irgendwie auf seinen Typ prüfen?

eine Art if(selectedItem===(*)QGraphicsPixmapItem)

im nächsten Schritt würde ich dann beim verschieben überprüfen, ob zB 10 px neben meinem aktiv verschiebbarem Item ein weiteres Item ist.

Verfasst: 15. Juni 2009 23:27
von franzf
marcwa hat geschrieben:Allerdings brauch ich den Zeiger nur, wenn es sich um ein PixmapItem handelt, kann ich den Zeiger irgendwie auf seinen Typ prüfen?
das nennt man cast. Und ein bisschen Doku liefert dir dann qgraphicsitem_cast.