[gelöst] Signal/Slot mit einem QGraphicsObject

Alles rund um die Programmierung mit Qt
Antworten
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

[gelöst] Signal/Slot mit einem QGraphicsObject

Beitrag von dd0815 »

Ich möchte ein Memory-Spiel programmieren (mein erstes Grafik-Programm mit Qt). In der Klasse MemoryControl (erbt public von QObject wegen Signal/Slots) werden QGraphicsView / QGraphicsScene verwaltet sowie die einzelnen Memory-Items (Klasse MemoryPiece) erstellt und in einer QList gesichert. Diese Klasse MemoryPiece (erbt public von QGraphicsObject) lädt 2 png´s in 2 pixmaps (Vorder-/Rückseite) und verarbeitet die Mausklick-Events.

Die Darstellung / Events funktionieren, nun möchte ich aber, dass bei einem Klick auf ein Item die Klasse MemoryControl überprüft, ob die Teile zueinanderpassen (durchsucht offene Teile in der QList und vergleicht Motiv-IDs). Dafür wollte ich das Signal/Slot-Prinzip nutzen (MemoryPiece emitted das Signal und ein Slot im MemoryControl wird aufgerufen), nur bekomme ich in Klasse MemoryPiece beim Kompilieren den Fehler:
<undefined reference to `memoryPiece::machWas(bool)'> (machWas ist der Testname des Signals)

Irgendetwas in der Klasse MemoryPiece ist noch nicht so wie es sein sollte, nur finde das ich leider nicht selbst :-(.

Wenn ich den Emit Aufruf mal auskommentiere kompiliert er fertig, bringt aber diese Ausgabe:
Object::connect: No such signal QGraphicsObject::machWas(bool) in ..\edutainSuite\src\memoryctrl.cpp:53

Da ich MemoryPiece von QGraphicsObject ableite, brauche ich doch nicht mehr das Makro Q_OBJECT im Header aufrufen, oder? (wenn ja bekomme ich zusätzlich folgende Fehler:
<undefined reference to `vtable for memoryPiece'>

Ist das Konzept an sich erst mal sinnvoll /würdet ihr das auch so realisieren oder kann ich das geschickter lösen? (z.B. Zugriff auf die Items)

ich benutze übrigens QtSDK 1.1.4 (soeben installiert) mit Qt4.8.0RC (OS WindowsXP / Win7)

bis später,
dd0815

Hier noch etwas Code:

Code: Alles auswählen

#ifndef MEMORYCTRL_H
#define MEMORYCTRL_H

#include <QtGui>
#include "memorypiece.h"

class memoryCtrl : public QObject //public QGraphicsView
{
    Q_OBJECT

public:

    memoryCtrl(QWidget *parent = 0);

public slots:
    void checkTest(bool);

signals:
    void sigTest(bool);

private:

    QList<memoryPiece*> piecelist;

    QGraphicsView *graphicsView;
    QGraphicsScene *graphicsScene;

};

#endif // MEMORYCTRL_H

Code: Alles auswählen

#include "memoryctrl.h"

memoryCtrl::memoryCtrl(QWidget *parent) : QObject(parent)
{

    graphicsScene = new QGraphicsScene(parent);

    graphicsView = new QGraphicsView(parent);
    graphicsView->setParent(parent);
    graphicsView->setScene(graphicsScene);
    graphicsView->setCacheMode(graphicsView->CacheBackground);
    graphicsView->setViewportUpdateMode(graphicsView->BoundingRectViewportUpdate);
    graphicsView->setRenderHint(QPainter::Antialiasing);
    graphicsView->setTransformationAnchor(graphicsView->AnchorUnderMouse);
    graphicsView->setResizeAnchor(graphicsView->AnchorViewCenter);
    graphicsView->showMaximized();

    graphicsScene->setSceneRect(0,
                                0,
                                graphicsView->parentWidget()->width(),
                                graphicsView->parentWidget()->height());

    QDir myDir("./memorySets/01/");
    QStringList list = myDir.entryList();

    QRegExp rx("p*.png");
    rx.setPatternSyntax(QRegExp::Wildcard);
    QStringList filter = list.filter(rx);

    int idx = 0;
    int max = filter.count();
    int posX = 200;
    int posY = 200;
    while ( idx < max)
    {

        memoryPiece *piece1 = new memoryPiece(filter.at(idx),idx,2,1);

        connect(piece1, SIGNAL(machWas(bool)),
                this,   SLOT(checkTest(bool))  );

        piece1->setPos(posX, posY);
        graphicsScene->addItem(piece1);

        piecelist.append(piece1);

        memoryPiece *piece2 = new memoryPiece(filter.at(idx),idx,2,2);
        piece2->setPos(posX, posY+110);
        graphicsScene->addItem(piece2);

        piecelist.append(piece2);

        QObject::connect(piece2, SIGNAL(machWas(bool)),
                this, SLOT(checkTest(bool)));

        posX += 180;
        idx++;

    }

    graphicsView->scale(qreal(1.0), qreal(1.0));
    graphicsView->setMinimumSize(1280, 1024);

}


void memoryCtrl::checkTest(bool bTest)
{
    qDebug() << "Ich müsste mal die Liste durchgehen";
}

Code: Alles auswählen

#ifndef MEMORYPIECE_H
#define MEMORYPIECE_H

#include <QtCore>
#include <QtGui>

class memoryPiece : public QGraphicsObject
{

public:

    memoryPiece(QString,int,int,int);

    QPixmap front;
    QPixmap back;

    int setID;
    int tiles;
    int tileNr;

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget);
    void mousePressEvent ( QGraphicsSceneMouseEvent * event );
    void mouseReleaseEvent( QGraphicsSceneMouseEvent * event );

signals:
    void machWas(bool);

private:

    bool visible;

};

#endif // MEMORYPIECE_H

Code: Alles auswählen

#include "memorypiece.h"

memoryPiece::memoryPiece(QString file, int isetID, int iTiles, int iTileNr)
{
    QString pixmap = QString("./memorySets/01/%1")
                             .arg(file);
    front.load(pixmap,0);
    back.load("./memorySets/01/back.png",0);
    visible = false;
    setID  = isetID;
    tiles  = iTiles;
    tileNr = iTileNr;
}

QRectF memoryPiece::boundingRect() const
{
    return QRectF(0,
                  0,
                  front.width(),
                  front.height());
}

void memoryPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget)
{
    if ( visible == true )
    {
        painter->drawPixmap(0, 0, front);
    }
    else
    {
        painter->drawPixmap(0, 0, back);
    }
}

void memoryPiece::mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
    visible = !visible;
    update(boundingRect());
    //emit machWas(true);
}

void memoryPiece::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
{
}
Zuletzt geändert von dd0815 am 3. Januar 2012 17:59, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von Christian81 »

MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von dd0815 »

Hallo Christian81,

vielen Dank für die schnelle Antwort.

Du meinst doch in der Klasse MemoryPiece? (in der anderen wird das Macro ja aufgerufen) Daher hatte ich in meinem 1. Posting folgendes gefragt:

Da ich MemoryPiece von QGraphicsObject ableite, brauche ich doch nicht mehr das Makro Q_OBJECT im Header aufrufen, oder? (wenn ja bekomme ich zusätzlich folgende Fehler:
<undefined reference to `vtable for memoryPiece'>

Ich habe auch schon stundenlang im Forum rumgesucht und auch diese Antwort an verschiedenen Stellen gefunden und (so gut ich eben konnte :-) ) überprüft

Habe auch schon bereinigen und neu erstellen versucht,
...

bis dann,
dd0815

Hier die genaue Ausgabe

Code: Alles auswählen

./debug\memorypiece.o: In function `memoryPiece':
C:\Daten\03_software\_Private\spiele\edutainSuite-build-desktop/../edutainSuite/src/memorypiece.cpp:3: undefined reference to `vtable for memoryPiece'
C:\Daten\03_software\_Private\spiele\edutainSuite-build-desktop/../edutainSuite/src/memorypiece.cpp:3: undefined reference to `vtable for memoryPiece'
C:\Daten\03_software\_Private\spiele\edutainSuite-build-desktop/../edutainSuite/src/memorypiece.cpp:3: undefined reference to `vtable for memoryPiece'
C:\Daten\03_software\_Private\spiele\edutainSuite-build-desktop/../edutainSuite/src/memorypiece.cpp:3: undefined reference to `vtable for memoryPiece'
collect2: ld returned 1 exit status
mingw32-make.exe[1]: *** [debug\edutainSuite.exe] Error 1
mingw32-make.exe: *** [debug] Error 2
17:34:14: Der Prozess "C:\Installation\QtSDK\mingw\bin\mingw32-make.exe" wurde mit dem Rückgabewert 2 beendet.
Fehler beim Erstellen des Projekts edutainSuite(Ziel: Desktop)
Bei der Ausführung von Build-Schritt 'Make'
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von Christian81 »

Welches Buildsystem? qmake? Dann vergessen die Header-Datei auch korrekt in der pro-Datei anzugeben - siehe http://developer.qt.nokia.com/doc/qt-4. ... ml#headers
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von dd0815 »

Hallo Christian81,

wie gesagt habe ich das QtSDK1.1.4 (mit MinGW), was qmake als Buildsystem hat.

Den Hinweis mit den Header-Dateien habe ich auch schon mehrfach gelesen, aber wenn die Headerdateien nicht gefunden würden, würde das Projekt ja nicht kompilieren (oder?)...

Die Dateien heißen memoryctrl.cpp/.h und memorypiece.cpp/.h und im Code die Klassen memoryCtrl / memoryPiece. Das Anlegen der Klassen habe ich dem QtCreator überlassen...

bis dann,
dd0815

Hier meine Projekt-Datei

Code: Alles auswählen

# QT += opengl \

HEADERS += src/mainWindow.h \
    src/datei.h \
    src/vismaku.h \
    src/visanlage.h \
    src/vismas.h \
    src/vistrans.h \
    src/memoryctrl.h \
    src/memorypiece.h

SOURCES += src/main.cpp \
    src/mainWindow.cpp \
    src/datei.cpp \
    src/vismaku.cpp \
    src/visanlage.cpp \
    src/vismas.cpp \
    src/vistrans.cpp \
    src/memoryctrl.cpp \
    src/memorypiece.cpp
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von Christian81 »

Wenn es schon in der pro-Datei drin stand dann nochmal etwas in der pro-Datei ändern damit qmake ausgeführt wird.
Und selbst mit dem SDK muss man nicht unbedingt qmake als Buildsystem haben - deshalb meine Frage.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Signal/Slot mit einem QGraphicsObject

Beitrag von dd0815 »

Hallo Christian81,

Sch...ön, das Ändern der Pro-Datei hat funktioniert :-)

Anscheinend hilft ein "Alles Bereinigen und Alles neu erstellen " nicht immer...

Vielen Dank für Deine schnelle Hilfe,
dd0815
Antworten