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.1k 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.
  • F ffej2ffej
    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.

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

    @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 1 Reply Last reply
    1
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #3

      Hi,

      Just in case, the Graphics View examples already provides several nice starting points.

      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 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