sygnal i sloty Qt

0

Witam

piszę sobie grę w Qt i graphicsview dokładnie chodzi o statki.

I tak

Mam klase QMainWindow (Q_OBJECT), klasę dziedziczącą po QGraphicsScene, klasę dziedziczącą po QGraphicsItem (pola na planszy) i ogólną klasę z mechaniką gry...

I w klasie od sceny mam tablice wskaźników do obiektów klasy od itemów oraz wskaźnik na obiekt klasy od gry i teraz chcę za pomocą sygnałów i slotów stworzyć taki mechanizm że jak klikne na item to on znika i wczytuje na to miejesce jakąś pixmape...dodam że korzystam z mousepressevent w klasie od QGpraphicsItem

i próbowałem tak

w klasie item :

bool MyItem::Click() // to jest public slot
{
    pressed = true;
    return pressed;
}

w klasie od sceny

void MyScene::drawObject() // to jest sygnal
{
    // jakiś kod który wczytuje pixmape czy rysuje coś od nowa
}

teraz connect próbowałem w konstruktorze sceny

connect(cell,SIGNAL(Click()),this,SLOT(drawObject()));

cell to wskaznik na tablice obiektów od MyItem

wyskakuje błąd, mniej więcej wiem dlaczego tak jest ale jak to rozwiązać ?

błąd:no matching function for call to 'MyScene::connect(MyItem* [25], const char*, MyScene* const, const char*)'

Ze slotami mam małe doświadczenie więc nie wiem czy dobrze kombinuję..

Kodu trochę mało dalem bo jeden wieli chaos panuje w projekcie, jak trzeba to do kleje więcej.

0

Cóż,raczej na pewno "const MyScene*" a nie "MyScene *const"
I przydałoby się,żebyś zapodał linijkę kodu w któej jest błąd oraz deklarację sygnału i slotu które chcesz łączyć

0

błąd wywala właśnie na :

connect(cell,SIGNAL(Click()),this,SLOT(drawObject()));

nie wiem czy tutaj moge dać this (czy musi być już utworzony obiekt sceny?), nie wiem czy również jeśli cell jest tablicą wskaźników na obiekt to samo cell wystarczy ?, no i SIGNAL(Click()) nie wiem jak się odwołać do sygnału ogólnie bez [] np. cell[0].Click()

to w MyScene

// wycinek z pliku.h

MyItem  *cell[25];

signals:
        void drawObject();

to w MyItem

public slots :
    bool Click();

Click wywołuje w mousePressEvent od MyItem

void MyItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Click();
    update();
    QGraphicsItem::mousePressEvent(event);
}
0

Ehh próbuje małymi kroczkami ale nie idzie;/

Każda klasa chcąca używać sygnałów i slotów musi posiadać marko Q_OBJECT ?

Więc do mojej klasy MyScene próbowałem dodać to macro w taki sposób :

plik.h

class MyScene : public QGraphicsScene
{
    Q_OBJECT
public:
        MyScene(QObject *parent = 0);

    // reszta kodu
}

i plik.cpp

konsturktor

MyScene::MyScene(QObject *parent) : QGraphicsScene(parent) // błąd
{
    // reszta kodu
}

destruktor

MyScene::~MyScene() // błąd
{
    //delete game;
    //delete []cell;
}

i wywala

błąd:undefined reference to `vtable for MyScene'

w pliku .cpp na liniach z konstruktorem i destruktorem ;[

0

próbowałeś przebudować projekt? Najlepiej wyczyść i zbuduj na nowo. QtCreator miewał problemy niegdyś z tym.

najlepiej wrzuć tutaj cały swój projekt jeśli nie jest to ściśle tajne wtedy może coś poradzimy.

0

Ok dzięki dałem wyczyść projekt, uruchom qmake, przebuduj projekt i działa :)

teraz przestudiuje jeszcze raz sloty i sygnały i powoli będę próbował to zaimplementować tak jak chciałem.

Jak by co temat jeszcze otwarty.

0

wszystko ładnie pięknie prawie dokończone tylko po kompilacji taki warring :

ostrzeżenie:Class MyItem implements the interface QGraphicsItem but does not list it in Q_INTERFACES. qobject_cast to QGraphicsItem will not work!

czyli nie da się używać S & S w klasie dziedziczącej po QGraphicsItem:) nie ma to jak cały dzień dochodzić do tego :)

0
k4myk napisał(a)

wszystko ładnie pięknie prawie dokończone tylko po kompilacji taki warring :

ostrzeżenie:Class MyItem implements the interface QGraphicsItem but does not list it in Q_INTERFACES. qobject_cast to QGraphicsItem will not work!

czyli nie da się używać S & S w klasie dziedziczącej po QGraphicsItem:) nie ma to jak cały dzień dochodzić do tego :)

Jakbyś zajrzał do dokumentacji nie miałbyś takich problemów. Aby móc korzystać z s&s klasa musi dziedziczyć bo QObject. Teraz masz kilka wyjść jak dodać s&s do swojej klasy.

0

Niestety nie mam pojecia jak to zrobić ;[

próbowałem w normalny sposób czyli klasę dziedziczyć po QObject i QGraphicsItem

0

To może utwórz sobie drugą klasę pomocniczą, która będzie dziedziczyć po QObject i umieść jej obiekt jako składowa klasy dziedziczącej po QGraphicsItem.

0

poza tym pokaż w jaki sposób dziedziczyłeś.

0

plik.h

class MyItem : public QObject,public QGraphicsItem
{
    Q_OBJECT
//....

}

plik.cpp

MyItem::MyItem(QObject *parent) : QObject(parent)
{
     //...
}

przy scenie takie coś działa ale teraz wiem że ona może korzystać z s&s w normalny sposób

0

poczytaj jeszcze o QGraphicsObjects, z tego co widzę dziedziczy właśnie po QObject i QGraphicsItem.

0

Ok, teraz klasa MyItem dziedziczy po QGraphicsObject i posiada makro QObject, żadnych ostrzeżeń nie ma więc jest szansa że wszystko będzie działać.

Tylko że znów wróciłem do punktu wyjścia, mianowicie nie wiem jak połączyć slot z klasy MyScene z sygnałem z klasy MyItem, jeśli w MyScene mam tablice wskaźników na obiekty MyItem...

próbuje tak jak w moim poscie 1 i 2, taki sam błąd otrzymuje.

0

co ty właściwie chcesz osiągnąć? Połączyć sygnał z każdego obiektu typu MyItem przechowywanego w tej tablicy z jednym slotem? Jeśli tak to przejdź przez tą tablicę i dla każdego elementu wywołaj connect'a albo poczytaj o QSignalMapper. Wszystko zależy od tego co chcesz zrobić

0

Tak dokładnie jak piszesz chce z tablicy obiektów każdy sygnał połaczyć do jednego slotu.

zrobiłem tak :

for (int i = 0; i<9; i++)
{
        connect(cell[i],SIGNAL(cell[i]->ItemIsClicked()),this,SLOT(narysuj_cos()));
}

kompilator podkreśla tą linijkę na czerwono ale skompilowało się bez błędów...

dokładnie jak napiszę :

cell[i]->ItemIsClicked()

nie wiem czy to moja wina ?

następnie dodałem

emit ItemIsClicked();

w mousepressevent w MyItem

oraz definicję slotu też w MyItem

void MyItem::ItemIsClicked()
{
}

lecz wywala :

błąd:multiple definition of `MyItem::ItemIsClicked()'
i pokazuje jako 1 definicję kod w pliku moc_myitem.cpp

void MyItem::ItemIsClicked()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

znów jak skasuję swoja definicję to się kompiluje ale pokazuje 9 razy (tyle ile tablica ma)

Object: No such signal MyItem::cell[i]->ItemIsClicked()

I bądź mądry :)

Poczytam jeszcze o QSignalMapper.

0

Zapodaj kod z pliku nagłówkowego od tego MyItem

0
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QtCore>
#include <QtGui>
#include <mygame.h>

class MyItem : public QGraphicsObject
{
    Q_OBJECT


    int X,Y,width,height;

public:

    MyItem(QGraphicsItem *parent = 0);
    MyItem(int x,int y, int w, int h);

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

    bool pressed;

    protected :

    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

signals:
    void ItemIsClicked();

};

#endif // MYITEM_H

nagłówków trochę dużo bo kod zmieniałem z 10 razy

0

mhm...tu wygląda dobrze.Jak wygląda tworzenie obiektu MyItem i łączenie sygnału ze ze slotem?Najbardziej o definicję tablicy mi idzie,oraz slotu do którego dołączasz

0

deklaracja w MyItem.h

MyItem  *cell[9];

tworzenie w MyItem.cpp

cell[0] = new MyItem(20,20,90,90);
cell[1] = new MyItem(130,20,90,90); 
// itd..

oczywiście dodaje na scenę i od razu to próbuję łączyć

for (int i = 0; i<9; i++)
{
        connect(cell[i],SIGNAL(cell[i]->ItemIsClicked()),this,SLOT(narysuj_cos()));
}

wszystko to w konstuktorze MyScene

i zostaje deklaracja slotu w MyScene.h

public slots :
        void narysuj_cos();

definicja w MyScene.cpp

void MyScene::narysuj_cos()
{
    addEllipse(10,10,340,340);
}

jeszcze dam drugi konstuktor MyItem bo w sumie przez niego tworzę obiekty

MyItem::MyItem(int x,int y, int w, int h) : X(x),Y(y),width(w),height(h)
{
    pressed = false;
    setFlag(ItemIsSelectable);
}
0

pomyłka deklaracja i tworzenie (pierwsze 2 kody) oczywiście w MyScene

0

Nie wywołujesz konstruktora tej klasy QGraphicsObject, więc może to być tego przyczyną.

edit: nie raczej to nie to, bo w sumie on się wywołuje automatycznie. W "MyScene" również wywołujesz Q_OBCJECT?

0

poszło i działa dobrze:)

powinno być tak :

connect(cell[i],SIGNAL(ItemIsClicked()),this,SLOT(narysuj_cos()));

chociaż dalej jak umieszczę definicję slota to wywala multiple definition (bo niby są dwie w pliku moc i .cpp) ale główne zadanie wykonane.

Dzięki:)

0

Mhm...no fajnie,ale gdzie jest dodawanie owych itemów z listy do sceny?

0

Oczywiście jest

for (int i = 0; i<9; i++)
{
        addItem(cell[i]);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1