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. QGraphicsObject: ContextMenu does not show up
Forum Updated to NodeBB v4.3 + New Features

QGraphicsObject: ContextMenu does not show up

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 4 Posters 1.3k Views 1 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.
  • S Offline
    S Offline
    sandro4912
    wrote on last edited by sandro4912
    #1

    I have a class derived from QGraphicsObject like this:

    class Room : public QGraphicsObject
    {
        Q_OBJECT
    public:
    
    //...
    public:
        QRectF boundingRect() const override;
    
        void paint(QPainter *painter,
                   const QStyleOptionGraphicsItem *option,
                   QWidget *widget) override;
    
    protected:
        void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
    
    //....
    }
    

    painting ect works already. Just the contextMenu does not show up. I implemented it like this:

    void Room::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
    {
        QAction guessWumpusAction{tr("&Has Wumpus")};
        guessWumpusAction.setCheckable(true);
        connect(&guessWumpusAction, &QAction::triggered, this, &Room::guessWumpus);
    
        QAction guessBatAction{tr("&Has Bat")};
        if (mHasBat) {
            guessBatAction.setChecked(true);
            guessBatAction.setEnabled(false);
        }
        else {
            guessBatAction.setCheckable(true);
        }
        connect(&guessBatAction, &QAction::triggered, this, &Room::guessBat);
    
        QAction guessPitAction{tr("&Has Pit")};
        guessPitAction.setCheckable(true);
        connect(&guessPitAction, &QAction::triggered, this, &Room::guessPit);
    
        QMenu menu;
        menu.addAction(&guessWumpusAction);
        menu.addAction(&guessBatAction);
        menu.addAction(&guessPitAction);
        menu.popup(event->screenPos());
    
        qDebug() << event->screenPos();
    }
    

    I can see that the event is called on mouse right click on the widget as expected. However the context Menu does not pop up. Whats wrong here?

    For test i call the class like this:

    #include <QApplication>
    
    #include "room.h"
    #include <QGraphicsView>
    #include <QGraphicsScene>
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        QGraphicsScene scene;
        QGraphicsView view;
        view.setScene(&scene);
    
        auto room = new Room;
        room->setVisible(true);
        scene.addItem(room);
    
        view.show();
        return QApplication::exec();
    }
    
    JonBJ 1 Reply Last reply
    0
    • S sandro4912

      I have a class derived from QGraphicsObject like this:

      class Room : public QGraphicsObject
      {
          Q_OBJECT
      public:
      
      //...
      public:
          QRectF boundingRect() const override;
      
          void paint(QPainter *painter,
                     const QStyleOptionGraphicsItem *option,
                     QWidget *widget) override;
      
      protected:
          void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
      
      //....
      }
      

      painting ect works already. Just the contextMenu does not show up. I implemented it like this:

      void Room::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
      {
          QAction guessWumpusAction{tr("&Has Wumpus")};
          guessWumpusAction.setCheckable(true);
          connect(&guessWumpusAction, &QAction::triggered, this, &Room::guessWumpus);
      
          QAction guessBatAction{tr("&Has Bat")};
          if (mHasBat) {
              guessBatAction.setChecked(true);
              guessBatAction.setEnabled(false);
          }
          else {
              guessBatAction.setCheckable(true);
          }
          connect(&guessBatAction, &QAction::triggered, this, &Room::guessBat);
      
          QAction guessPitAction{tr("&Has Pit")};
          guessPitAction.setCheckable(true);
          connect(&guessPitAction, &QAction::triggered, this, &Room::guessPit);
      
          QMenu menu;
          menu.addAction(&guessWumpusAction);
          menu.addAction(&guessBatAction);
          menu.addAction(&guessPitAction);
          menu.popup(event->screenPos());
      
          qDebug() << event->screenPos();
      }
      

      I can see that the event is called on mouse right click on the widget as expected. However the context Menu does not pop up. Whats wrong here?

      For test i call the class like this:

      #include <QApplication>
      
      #include "room.h"
      #include <QGraphicsView>
      #include <QGraphicsScene>
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
      
          QGraphicsScene scene;
          QGraphicsView view;
          view.setScene(&scene);
      
          auto room = new Room;
          room->setVisible(true);
          scene.addItem(room);
      
          view.show();
          return QApplication::exec();
      }
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @sandro4912
      Two guesses:
      Are your co-ordinates right in menu.popup(event->screenPos()) (no mapping needed, I don't know)?
      Your QMenu menu goes out of scope immediately after popup() (not exec())? You would need outside storage if you want to use popup(); test it with exec() instead? (I think it's this regardless of first point.)

      1 Reply Last reply
      3
      • S Offline
        S Offline
        sandro4912
        wrote on last edited by
        #3

        I added exec and now it shows up. I could swear i saw an example with only popup. However now that it shows up it is only is triggered when I right click in the first 1/4 of the widget.(like if the widget has half the height and width.

        I define boundingRect like this:

        QRectF Room::boundingRect() const
        {
            return QRectF{ QPointF{0, 0}, roomImage().size()};
        }
        

        were roomImage is a ressource:

        QImage Room::roomImage() const
        {
            return QImage{":/ressources/room.png"};
        }
        

        to paint i do this:

        void Room::paint(
                QPainter *painter,
                const QStyleOptionGraphicsItem *option,
                QWidget *widget)
        {
            Q_UNUSED(option)
            Q_UNUSED(widget)
        
            drawRoom(painter);
        }
        
        void Room::drawRoom(QPainter *painter)
        {
            painter->drawImage(boundingRect(), roomImage());
        }
        
        JonBJ 1 Reply Last reply
        0
        • S sandro4912

          I added exec and now it shows up. I could swear i saw an example with only popup. However now that it shows up it is only is triggered when I right click in the first 1/4 of the widget.(like if the widget has half the height and width.

          I define boundingRect like this:

          QRectF Room::boundingRect() const
          {
              return QRectF{ QPointF{0, 0}, roomImage().size()};
          }
          

          were roomImage is a ressource:

          QImage Room::roomImage() const
          {
              return QImage{":/ressources/room.png"};
          }
          

          to paint i do this:

          void Room::paint(
                  QPainter *painter,
                  const QStyleOptionGraphicsItem *option,
                  QWidget *widget)
          {
              Q_UNUSED(option)
              Q_UNUSED(widget)
          
              drawRoom(painter);
          }
          
          void Room::drawRoom(QPainter *painter)
          {
              painter->drawImage(boundingRect(), roomImage());
          }
          
          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @sandro4912
          popup() can be used, but not with a stack variable QMenu like you had. Usually you'd new it.

          For the area now: does ":/ressources/room.png" match how you spell resources on disk? Or you need to look at roomImage().size().

          1 Reply Last reply
          1
          • S Offline
            S Offline
            sandro4912
            wrote on last edited by
            #5

            if i create menu dynamically who deallocates it later? I can't assign the Room to it as a parent since is not derrived from QWidget.

            Also i tryed:

            void Room::drawRoom(QPainter *painter)
            {
                qDebug() << boundingRect();
                qDebug() << roomImage().size();
            
                painter->drawImage(boundingRect(), roomImage());
            }
            

            Which outputs:

            QRectF(0,0 100x100)
            QSize(100, 100)
            

            So it should theoretically pop the menu in the whole image but it doesn't?

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

              Hi,

              Make it a member variable and delete it in your class destructor.

              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
              2
              • S sandro4912

                if i create menu dynamically who deallocates it later? I can't assign the Room to it as a parent since is not derrived from QWidget.

                Also i tryed:

                void Room::drawRoom(QPainter *painter)
                {
                    qDebug() << boundingRect();
                    qDebug() << roomImage().size();
                
                    painter->drawImage(boundingRect(), roomImage());
                }
                

                Which outputs:

                QRectF(0,0 100x100)
                QSize(100, 100)
                

                So it should theoretically pop the menu in the whole image but it doesn't?

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @sandro4912
                For dynamically created QMenu, then as @SGaist says.

                But are you sure you need QMenu:popUp() and not just QMenu::exec() for your use case? It depends how you want it to work. If the simple exec() suffices you should be able to just use a stack (local) variable QMenu menu. You don't need the menu after it has returned the action the user clicked.

                For your coordinates/click area, I don't think we're going to know. Is your image indeed 100x100 size, or is that maybe some default? Why don't you play with a bigger/smaller image and see what the pattern is?

                1 Reply Last reply
                1
                • S Offline
                  S Offline
                  sandro4912
                  wrote on last edited by sandro4912
                  #8

                  there is nothing wrong with the image but to sort it out i did this:

                  void Room::paint(
                          QPainter *painter,
                          const QStyleOptionGraphicsItem *option,
                          QWidget *widget)
                  {
                      QRectF rect{boundingRect()};
                      painter->setPen(Qt::black);
                      painter->drawRect(rect);
                  }
                  
                  QRectF Room::boundingRect() const
                  {
                      return QRectF{ 0, 0, 200, 200};
                  }
                  

                  Still the Menu is not popped up on the whole rect. It only appeas like on 1/3 of the size of QRectF{ 0, 0, 200, 200}; so is not always half. Does contextMenuEvent maybe check the size from somewhere else but not from the boundingRect ? Or is this simply a bug in QT?

                  I also compiled the code an a second OS to sort out that its not annother bug with KDE/Neon. But on Windows 10 same behaviour.

                  Also I stayed with the local Menu:

                  void Room::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
                  {
                      qDebug() << boundingRect();
                      qDebug() << roomImage().size();
                  
                      QMenu menu;
                      menu.addAction(mGuessWumpusAction);
                      menu.addAction(mGuessBatAction);
                      menu.addAction(mGuessPitAction);
                      menu.exec(event->screenPos());
                  }
                  

                  Any more ideas??

                  Christian EhrlicherC 1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    sandro4912
                    wrote on last edited by
                    #9

                    let me know if you need more information to find a solution for this issue. Maybe is even a qt bug.

                    1 Reply Last reply
                    0
                    • S sandro4912

                      there is nothing wrong with the image but to sort it out i did this:

                      void Room::paint(
                              QPainter *painter,
                              const QStyleOptionGraphicsItem *option,
                              QWidget *widget)
                      {
                          QRectF rect{boundingRect()};
                          painter->setPen(Qt::black);
                          painter->drawRect(rect);
                      }
                      
                      QRectF Room::boundingRect() const
                      {
                          return QRectF{ 0, 0, 200, 200};
                      }
                      

                      Still the Menu is not popped up on the whole rect. It only appeas like on 1/3 of the size of QRectF{ 0, 0, 200, 200}; so is not always half. Does contextMenuEvent maybe check the size from somewhere else but not from the boundingRect ? Or is this simply a bug in QT?

                      I also compiled the code an a second OS to sort out that its not annother bug with KDE/Neon. But on Windows 10 same behaviour.

                      Also I stayed with the local Menu:

                      void Room::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
                      {
                          qDebug() << boundingRect();
                          qDebug() << roomImage().size();
                      
                          QMenu menu;
                          menu.addAction(mGuessWumpusAction);
                          menu.addAction(mGuessBatAction);
                          menu.addAction(mGuessPitAction);
                          menu.exec(event->screenPos());
                      }
                      

                      Any more ideas??

                      Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @sandro4912 said in QGraphicsObject: ContextMenu does not show up:

                      Still the Menu is not popped up on the whole rect. It only appeas like on 1/3 of the size of QRectF{ 0, 0, 200, 200}; so is not always half. Does contextMenuEvent maybe check the size from somewhere else but not from the boundingRect ?

                      I don't understand what you say here - does the popup / context menu event only works on 1/3 of your widget? Is the popup not as big as you expect?

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        sandro4912
                        wrote on last edited by
                        #11

                        the popup itself looks perfect.

                        The problem is it does not get triggered in the whole 200x200 area of the widget. It only looks like it gets shown in a smaller rectangle from the top left point.

                        so in 200x200 maybe only in 80x80 from top left point it gets created.

                        I would expect in the whole rectangle the context menu gets triggere.

                        maybe i should make a minimal running example so it can be verifyed.

                        1 Reply Last reply
                        0
                        • Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Ok, now it's clear to me. There are two examples (diagramscene, boxes) which work fine for me. Maybe you can try them out.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            sandro4912
                            wrote on last edited by
                            #13

                            I made a minimal program and it works:

                            #ifndef RECTANGLE_H
                            #define RECTANGLE_H
                            
                            #include <QGraphicsObject>
                            
                            class Rectangle : public QGraphicsObject
                            {
                                Q_OBJECT
                            public:
                                explicit Rectangle(QGraphicsObject *parent = nullptr);
                            
                                QRectF boundingRect() const override;
                            
                                void paint(QPainter *painter,
                                           const QStyleOptionGraphicsItem *option,
                                           QWidget *widget) override;
                            
                            protected:
                                void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
                            };
                            
                            #endif // RECTANGLE_H
                            
                            #include "rectangle.h"
                            
                            #include <QGraphicsSceneContextMenuEvent>
                            #include <QPainter>
                            #include <QMenu>
                            
                            Rectangle::Rectangle(QGraphicsObject *parent)
                                : QGraphicsObject(parent)
                            {
                            }
                            
                            QRectF Rectangle::boundingRect() const
                            {
                                return QRectF{ 0, 0, 100, 100};
                            }
                            
                            void Rectangle::paint(
                                    QPainter *painter,
                                    const QStyleOptionGraphicsItem *option,
                                    QWidget *widget)
                            {
                                Q_UNUSED(option)
                                Q_UNUSED(widget)
                            
                                QRectF rect{boundingRect()};
                                painter->setPen(Qt::black);
                                painter->drawRect(rect);
                            }
                            
                            void Rectangle::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
                            {
                                QMenu menu;
                                menu.addAction("Action 1");
                                menu.addAction("Action 2");
                                menu.exec(event->screenPos());
                            }
                            
                            #include "rectangle.h"
                            
                            #include <QApplication>
                            #include <QGraphicsScene>
                            #include <QGraphicsView>
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication app(argc, argv);
                            
                                QGraphicsScene scene;
                            
                                Rectangle rectangle;
                                scene.addItem(&rectangle);
                            
                                QGraphicsView view;
                                view.setScene(&scene);
                            
                                view.show();
                                return QApplication::exec();
                            }
                            

                            Everything fine here the popup shows up in all the widget. The reason it does not work in my programm is. At some point i changed the class from QGraphicsObject to QGraphicsWidget. If we modify the minimal programm to have QGraphicsWidget as a base for Rectangle we get the Issue again:

                            #ifndef RECTANGLE_H
                            #define RECTANGLE_H
                            
                            #include <QGraphicsWidget>
                            
                            class Rectangle : public QGraphicsWidget
                            {
                                Q_OBJECT
                            public:
                                explicit Rectangle(QGraphicsWidget *parent = nullptr);
                            
                                QRectF boundingRect() const override;
                            
                                void paint(QPainter *painter,
                                           const QStyleOptionGraphicsItem *option,
                                           QWidget *widget) override;
                            
                            protected:
                                void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
                            };
                            
                            #endif // RECTANGLE_H
                            
                            #include "rectangle.h"
                            
                            #include <QGraphicsSceneContextMenuEvent>
                            #include <QPainter>
                            #include <QMenu>
                            
                            Rectangle::Rectangle(QGraphicsWidget *parent)
                                : QGraphicsWidget(parent)
                            {
                            }
                            
                            QRectF Rectangle::boundingRect() const
                            {
                                return QRectF{ 0, 0, 100, 100};
                            }
                            
                            void Rectangle::paint(
                                    QPainter *painter,
                                    const QStyleOptionGraphicsItem *option,
                                    QWidget *widget)
                            {
                                Q_UNUSED(option)
                                Q_UNUSED(widget)
                            
                                QRectF rect{boundingRect()};
                                painter->setPen(Qt::black);
                                painter->drawRect(rect);
                            }
                            
                            void Rectangle::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
                            {
                                QMenu menu;
                                menu.addAction("Action 1");
                                menu.addAction("Action 2");
                                menu.exec(event->screenPos());
                            }
                            
                            #include "rectangle.h"
                            
                            #include <QApplication>
                            #include <QGraphicsScene>
                            #include <QGraphicsView>
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication app(argc, argv);
                            
                                QGraphicsScene scene;
                            
                                Rectangle rectangle;
                                scene.addItem(&rectangle);
                            
                                QGraphicsView view;
                                view.setScene(&scene);
                            
                                view.show();
                                return QApplication::exec();
                            }
                            

                            So why is the behaviour different with QGraphicWidget? How can it get fixed there?

                            1 Reply Last reply
                            0
                            • Christian EhrlicherC Offline
                              Christian EhrlicherC Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by Christian Ehrlicher
                              #14

                              You forgot to set a proper size of the QGraphicsWidget: https://doc.qt.io/qt-5/qgraphicswidget.html#size-prop - since it's a widget you have to treat it like a widget which also means you have to set a proper size since there is no layout from where the size could be calculated from.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              1 Reply Last reply
                              2
                              • S Offline
                                S Offline
                                sandro4912
                                wrote on last edited by
                                #15

                                I solved the issue by resize in the constructor:

                                    resize(boundingRect().size());
                                

                                That should be it or any other things to concern?

                                1 Reply Last reply
                                0
                                • Christian EhrlicherC Offline
                                  Christian EhrlicherC Offline
                                  Christian Ehrlicher
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #16

                                  @sandro4912 said in QGraphicsObject: ContextMenu does not show up:

                                  That should be it or any other things to concern?

                                  That's fine.

                                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                  Visit the Qt Academy at https://academy.qt.io/catalog

                                  1 Reply Last reply
                                  0

                                  • Login

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