QGraphicsView - Aufbau/Items verschieben/Signale

Alles rund um die Programmierung mit Qt
Antworten
marcwa
Beiträge: 4
Registriert: 14. Juni 2009 21:55

QGraphicsView - Aufbau/Items verschieben/Signale

Beitrag 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
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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
marcwa
Beiträge: 4
Registriert: 14. Juni 2009 21:55

Beitrag 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?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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()).
marcwa
Beiträge: 4
Registriert: 14. Juni 2009 21:55

Beitrag 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.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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.
Antworten