Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. drags, drops, signals and slots of QGraphicsPixmapItem(s)...
Qt 6.11 is out! See what's new in the release blog

drags, drops, signals and slots of QGraphicsPixmapItem(s)...

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 3 Posters 2.2k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mrjjM mrjj

    @ffej2ffej said in drags, drops, signals and slots of QGraphicsPixmapItem(s)...:

    I am creating a project which someday will resemble the game called freecell. I'm still new-ish to QT, so I'm learning as I go along.
    For this game, I have created a QGraphicsScene which, once I've added all the elements, (cards in this case) will be contained by a QGraphicsView. So far it's going fairly well. By that I mean I can place the cards (which are descendants of QGraphicsPixmapItem) into the scene using the addItem() function of the scene. Before being placed, the cards are made mobile using the setFlag() method with the parameters of (QGraphicsItem::ItemIsMoveable,true).
    So now I have cards and the user is free to move them anywhere within the scene. What I need to do is restrict the places where the card may be dropped or, if that's not possible, changing the location of the card (setPos()) after it's dropped to a place that I've decided is appropriate. I also would like to be able to examine the card when it's first clicked with intent to move, so the program can decide if there are other cards below it which must move also.
    My guess is that each card probably sends a signal when it's clicked, when it's moved, when it's finished moving and when it's un-clicked. I think the scene will probably contain the slot that will react to these signals. I don't know if this is accurate and even if it is, I don't know what the names of the signals or the slot(s) are. Obviously, I have to override the existing slot(s) and connect them to the appropriate signals so I will need to know what they're called. I've spent a considerable amount of time searching the help regarding QGraphicsView, QGraphicsItem, QGraphicsScene, etc. but have not been able to find out this information. I looked through the help and tutorials for solutions to my needs, but the only thing I can find is a tutorial that starts with creating a drag and doing other things. I don't want to create a drag, I want to REACT to a drag.
    I am also aware that the possibility exists that I'm thinking about this completely the wrong way and there's actually another easy way to do it. I'd like to hear from the learned minds of QT users to set me straight.

    Wow. Wall ;)

    anyway, i think you can use
    https://doc.qt.io/qt-5/qgraphicsitem.html#itemChange
    with this
    https://doc.qt.io/qt-5/qgraphicsitem.html#GraphicsItemChange-enum

    QGraphicsItem::ItemPositionChange

    as you can see from sample in first link. its possible to return another pos and that gives the ability
    to snap to cards or return the orginal value to cancel move.

    note.
    you most likely need to do
    setFlag( QGraphicsItem::ItemSendsScenePositionChanges, true );
    for the items to have it send the needed info.

    here is sample that snaps to a grid.
    https://www.walletfox.com/course/qgraphicsitemsnaptogrid.php

    F Offline
    F Offline
    ffej2ffej
    wrote on last edited by
    #4

    @mrjj I read the pages referred in your reply and added the ItemPositionHasChanged() function into the Card object. I also added the setFlag(QGraphicsItem::ItemSendsGeometryChanges,true) statement per the documentation.
    The function was not called when I moved the items with the mouse so I added 2 setPos() statements into the object that creates and places the cards. It still didn't call the ItemPositionHasChanged() function. AAAaaaargh!
    P.S. I tested whether the function was called by adding a qDebug("some text") statement to the function. No qDebugs occurred.

    mrjjM 1 Reply Last reply
    0
    • F ffej2ffej

      @mrjj I read the pages referred in your reply and added the ItemPositionHasChanged() function into the Card object. I also added the setFlag(QGraphicsItem::ItemSendsGeometryChanges,true) statement per the documentation.
      The function was not called when I moved the items with the mouse so I added 2 setPos() statements into the object that creates and places the cards. It still didn't call the ItemPositionHasChanged() function. AAAaaaargh!
      P.S. I tested whether the function was called by adding a qDebug("some text") statement to the function. No qDebugs occurred.

      mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #5

      @ffej2ffej
      Hi
      did you use the override keyword to be truly sure you did get function
      signature 100% right ?
      Without code, its hard to guess at :)

      F 1 Reply Last reply
      0
      • mrjjM mrjj

        @ffej2ffej
        Hi
        did you use the override keyword to be truly sure you did get function
        signature 100% right ?
        Without code, its hard to guess at :)

        F Offline
        F Offline
        ffej2ffej
        wrote on last edited by
        #6

        @mrjj
        Here is all the code with horizontal dividers to distinguish the beginnings and endings of all the files.
        ---------------------------------------card.h----------------------------------------
        #ifndef CARD_H
        #define CARD_H
        #include <QGraphicsPixmapItem>
        #include <QGraphicsSceneDragDropEvent>

        class Card : public QGraphicsPixmapItem
        {
        public:
        Card();
        int suit;
        int number;
        void setSuit(int sentSuit);
        void setNumber(int sentNumber);
        protected:
        //void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override;
        void QGraphicsPixmapItem::ItemPositionHasChanged() override;
        };

        #endif // CARD_H
        -----------------------------------end of card.h-------------------------------------

        ----------------------------------card.cpp-------------------------------------------
        #include "card.h"
        #include <QDebug>

        Card::Card()
        {
        //ItemSendsGeometryChanges
        }

        void ItemPositionHasChanged()
        {
        qDebug("Card has moved.");
        }
        ------------------------------------end of card.cpp----------------------------------
        -------------------------------------game.h------------------------------------------
        #ifndef GAME_H
        #define GAME_H
        #include <QGraphicsView>

        class Game : public QGraphicsView
        {
        public:
        Game();//constructor (duh!)
        };

        #endif // GAME_H
        -----------------------------------end of game.h-------------------------------------
        ------------------------------------game.cpp-----------------------------------------
        #include "game.h"
        #include <QGraphicsScene>
        #include <card.h>
        #include <QImage>

        Game::Game()
        {
        QGraphicsScene *scene = new QGraphicsScene();
        Card *card1 = new Card();
        Card *card2 = new Card();
        Card *bigCard = new Card();
        card1->setPixmap(QPixmap(":/images/1s.png"));
        card2->setPixmap(QPixmap(":/images/2s.png"));
        bigCard->setPixmap(QPixmap(":/images/1sbigger.png"));
        card1->setFlag(QGraphicsItem::ItemIsMovable,true);
        card2->setFlag(QGraphicsItem::ItemIsMovable,true);
        bigCard->setFlag(QGraphicsItem::ItemIsMovable,true);
        bigCard->setFlag(QGraphicsItem::ItemSendsGeometryChanges,true);
        card1->setPos(0,0);
        card2->setPos(20,0);
        bigCard->setPos(30,30);//arbitrary numbers. Sometimes a cigar is just a cigar.
        scene->addItem(card1);
        scene->addItem(card2);
        scene->addItem(bigCard);
        QGraphicsView *theview = new QGraphicsView(scene);
        theview->show();
        theview->setFixedSize(800,600);//make sure to adjust this to a proper size for the game!!!!!!!!!!!!!!!!!!!!!
        scene->setSceneRect(0,0,800,600);
        setBackgroundBrush(QBrush(QImage(":/images/cardsMoveBG.png")));//Doesn't work here or on the video game from tutorial.
        bigCard->setPos(40,40);
        bigCard->setPos(50,50);
        }
        -----------------------------------------end of game.cpp-------------------------------
        --------------------------------------------main.cpp-----------------------------------
        #include <QApplication>
        #include "game.h"

        int main(int argc, char *argv[])
        {
        QApplication a(argc, argv);
        Game *theGame = new Game();
        //theGame->show();//this is weird. It shows some mysterious window that is NOT the window I created and specificied all the
        //contents, etc. However, if I don't create a Game object, nothing shows at all.

        return a.exec();
        

        }
        ----------------------------------------end of main.cpp-------------------------------

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #7

          Why are you creating a subclass of QGrapchicsView in which you create a QGraphicsView object and show that one separately ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          F 1 Reply Last reply
          1
          • F Offline
            F Offline
            ffej2ffej
            wrote on last edited by
            #8

            BTW, I sent the code with the override specified. I cannot, however, compile with it like that because it causes an error.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #9

              The error being that it's not overriding anything known ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • SGaistS SGaist

                Why are you creating a subclass of QGrapchicsView in which you create a QGraphicsView object and show that one separately ?

                F Offline
                F Offline
                ffej2ffej
                wrote on last edited by
                #10

                @SGaist I opened and studied both the 40,000 chips and the robot drag&drop examples. I'm afraid I could not figure out how they worked or how I could apply them to my work. Maybe I'm too stoopid to be a programmer. I miss doing assembly language where you simply put a character (optionally, a color too) in a memory spot and it appears on the screen. In graphics modes, you instructed BIOS of the color you want at the x and y coordinates you want then called a function and it appeared. I'm glad they simplified it for c++, he said sarcastically.

                mrjjM 1 Reply Last reply
                0
                • F ffej2ffej

                  @SGaist I opened and studied both the 40,000 chips and the robot drag&drop examples. I'm afraid I could not figure out how they worked or how I could apply them to my work. Maybe I'm too stoopid to be a programmer. I miss doing assembly language where you simply put a character (optionally, a color too) in a memory spot and it appears on the screen. In graphics modes, you instructed BIOS of the color you want at the x and y coordinates you want then called a function and it appeared. I'm glad they simplified it for c++, he said sarcastically.

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #11

                  @ffej2ffej
                  Hi
                  Well the step from good old direct framebuffer writing - to full blown object orientated
                  GUI building is not trivial so some stumbling blocks are to be expected.
                  The code looks ok but Game class IS a QGraphicsView already so no need to
                  create another inside Game constructor.
                  QGraphicsView *theview = new QGraphicsView(scene); // seems not needed.
                  so should fix that, OR remove the class Game : public QGraphicsView
                  part so its a clean class and then let it setup the View. ( as you do in that code)

                  However, im not sure what exact error you get so its hard to help.

                  F 1 Reply Last reply
                  1
                  • F Offline
                    F Offline
                    ffej2ffej
                    wrote on last edited by
                    #12

                    If I state
                    void QGraphicsPixmapItem::ItemPositionHasChanged() override;
                    I get
                    non-friend class member 'ItemPositionHasChanged' cannot have a qualified name

                    If I state
                    void ItemPositionHasChanged() override;
                    I get
                    only virtual member functions can be marked 'override'
                    I wish I knew what either of those errors MEANT, let alone how to solve them.

                    1 Reply Last reply
                    0
                    • mrjjM mrjj

                      @ffej2ffej
                      Hi
                      Well the step from good old direct framebuffer writing - to full blown object orientated
                      GUI building is not trivial so some stumbling blocks are to be expected.
                      The code looks ok but Game class IS a QGraphicsView already so no need to
                      create another inside Game constructor.
                      QGraphicsView *theview = new QGraphicsView(scene); // seems not needed.
                      so should fix that, OR remove the class Game : public QGraphicsView
                      part so its a clean class and then let it setup the View. ( as you do in that code)

                      However, im not sure what exact error you get so its hard to help.

                      F Offline
                      F Offline
                      ffej2ffej
                      wrote on last edited by
                      #13

                      @mrjj The problem about the notifications of dragging and dropping are still unsolved but I want to thank you for pointing out the fact that I had made the Game object a descendant of QGraphicsView. The details of how I made that mistake are long a boring and suffice to say I've fixed it. I still, however, am not notified when the user drags and drops a card.

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #14

                        @ffej2ffej said in drags, drops, signals and slots of QGraphicsPixmapItem(s)...:

                        ItemPositionHasChanged

                        Aren't you trying to override an enum value ?

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        1
                        • mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #15

                          Hi
                          Its
                          QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
                          it has to match exactly.

                          1 Reply Last reply
                          2

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved