Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How do you handle selection of QGraphicsItem?
Qt 6.11 is out! See what's new in the release blog

How do you handle selection of QGraphicsItem?

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 3 Posters 2.6k Views 2 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.
  • JonBJ JonB

    @Emon-Haque
    I have not followed your code. But in each of these ...Event overrides you do not allow the event to proceed through to default handling (by calling base method), is that what is causing whatever your behaviour is?

    ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #4

    @JonB, First, added QGraphicsItem::...Event(e); in the beginning of each function. Second, removed those from beginning and added at the end of each function and third, in addition to those in the end of hoverEvents, added same before return. Didn't work!

    Pl45m4P 1 Reply Last reply
    0
    • ? A Former User

      @JonB, First, added QGraphicsItem::...Event(e); in the beginning of each function. Second, removed those from beginning and added at the end of each function and third, in addition to those in the end of hoverEvents, added same before return. Didn't work!

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #5

      @Emon-Haque

      The default implementation calls update(); otherwise it does nothing.

      • https://doc.qt.io/qt-5/qgraphicsitem.html#hoverEnterEvent

      The default implementation will update your item. When you dont call it, it could lead to unwanted bahavior.


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      ? 1 Reply Last reply
      0
      • Pl45m4P Pl45m4

        @Emon-Haque

        Do you call the base class' c'tor in Slice() while creating your Slice?
        Also, like @JonB said: Pass the event to the base class in your overriden functions (call the base event handler).
        E.g:

        void Slice::hoverEnterEvent(QGraphicsSceneHoverEvent* ev){
        // ....
        QGraphicsItem::hoverEnterEvent(ev);
        }
        

        Edit:

        Show your Slice constructor

        ? Offline
        ? Offline
        A Former User
        wrote on last edited by A Former User
        #6

        @Pl45m4, didn't have that in constructor. Tried this:

        Slice::Slice(float start, float sweep, QColor color, QRectF rect, PieSeries& series, QGraphicsItem *parent)
            : QGraphicsItem(parent), m_start(start), m_sweep(sweep), m_color(color), m_series(series)
        {...}
        

        with and without those base event calls mentioned in reply to @JonB. Didn't work.

        EDIT
        Here's the whole content:

        #define whats16 16
        Slice::Slice(float start, float sweep, QColor color, QRectF rect, PieSeries& series, QGraphicsItem *parent)
            : QGraphicsItem(parent), m_start(start), m_sweep(sweep), m_color(color), m_series(series){
            m_realColor = color;
            m_rect = rect;
            m_path = QPainterPath(QPointF(m_rect.width() / 2, m_rect.height() / 2));
            m_path.arcTo(m_rect, -m_start, -m_sweep);
            m_path.closeSubpath();
            dx = 10 * cos((m_start + m_sweep / 2) * M_PI / 180);
            dy = 10 * sin((m_start + m_sweep / 2) * M_PI / 180);
            float dimension = m_rect.width() + 2 * 20;
            m_boundingRect = QRectF(-20, -20, dimension, dimension);
            setAcceptHoverEvents(true);
            setFlag(QGraphicsItem::ItemIsSelectable);
        }
        

        EDIT

        and for the working example, you can get all code of different classes/struct here

        1 Reply Last reply
        0
        • Pl45m4P Pl45m4

          @Emon-Haque

          The default implementation calls update(); otherwise it does nothing.

          • https://doc.qt.io/qt-5/qgraphicsitem.html#hoverEnterEvent

          The default implementation will update your item. When you dont call it, it could lead to unwanted bahavior.

          ? Offline
          ? Offline
          A Former User
          wrote on last edited by
          #7

          @Pl45m4, with QGraphicsItem(parent) in the constructor, added update() at the end of each of those three event handlers with and without calling base QGraphicsItem::...Event(e). Didn't work

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #8

            You can download the project from GitHub to avoid copy/paste and refactoring.

            Pl45m4P 1 Reply Last reply
            0
            • ? A Former User

              You can download the project from GitHub to avoid copy/paste and refactoring.

              Pl45m4P Offline
              Pl45m4P Offline
              Pl45m4
              wrote on last edited by
              #9

              @Emon-Haque

              I will try later with a minimal example to test the hover behavior.
              Usually it should work, unless you have done something else wrong.

              Does mouseOver do something with you item?
              Better use qobject_cast to cast QObjects.

              auto view = static_cast<PieView*>(scene()->parent());
              emit view->mouseOver(m_series);


              If debugging is the process of removing software bugs, then programming must be the process of putting them in.

              ~E. W. Dijkstra

              ? 1 Reply Last reply
              0
              • Pl45m4P Pl45m4

                @Emon-Haque

                I will try later with a minimal example to test the hover behavior.
                Usually it should work, unless you have done something else wrong.

                Does mouseOver do something with you item?
                Better use qobject_cast to cast QObjects.

                auto view = static_cast<PieView*>(scene()->parent());
                emit view->mouseOver(m_series);

                ? Offline
                ? Offline
                A Former User
                wrote on last edited by A Former User
                #10

                @Pl45m4, in mouseOver I add an ellipse (ellipse = new QGraphicsEllipseItem();) in the scene and that ellipse has a text (text = new QGraphicsTextItem(ellipse);):

                void PieView::onMouseOver(PieSeries &s){
                    text->document()->clear();
                    auto cursor = QTextCursor(text->document());
                    QTextBlockFormat blockFormat;
                    QTextCharFormat charFormat;
                
                    blockFormat.setAlignment(Qt::AlignHCenter);
                    charFormat.setForeground(Qt::darkGreen);
                    charFormat.setFontPointSize(16);
                    cursor.setBlockFormat(blockFormat);
                    cursor.setBlockCharFormat(charFormat);
                    cursor.insertText(s.name);
                
                    charFormat.setForeground(Qt::red);
                    charFormat.setFontPointSize(14);
                    cursor.insertBlock(blockFormat, charFormat);
                    cursor.insertText(QString::number(s.value));
                
                    charFormat.setForeground(Qt::black);
                    charFormat.setFontPointSize(12);
                    cursor.insertBlock(blockFormat, charFormat);
                    cursor.insertText(QString::number(s.value / m_total * 100) + "%");
                
                    text->setY(ellipse->boundingRect().center().y() - text->boundingRect().height()/2);
                    scene()->addItem(ellipse);
                }
                

                and I remove that onMouseLeave: void PieView::onMouseLeave(){ scene()->removeItem(ellipse); }. PieView is the subclass of QGraphicsView.

                EDIT
                Will change that static to qobject cast later. Thanks for the reminder.

                JonBJ 1 Reply Last reply
                0
                • ? A Former User

                  @Pl45m4, in mouseOver I add an ellipse (ellipse = new QGraphicsEllipseItem();) in the scene and that ellipse has a text (text = new QGraphicsTextItem(ellipse);):

                  void PieView::onMouseOver(PieSeries &s){
                      text->document()->clear();
                      auto cursor = QTextCursor(text->document());
                      QTextBlockFormat blockFormat;
                      QTextCharFormat charFormat;
                  
                      blockFormat.setAlignment(Qt::AlignHCenter);
                      charFormat.setForeground(Qt::darkGreen);
                      charFormat.setFontPointSize(16);
                      cursor.setBlockFormat(blockFormat);
                      cursor.setBlockCharFormat(charFormat);
                      cursor.insertText(s.name);
                  
                      charFormat.setForeground(Qt::red);
                      charFormat.setFontPointSize(14);
                      cursor.insertBlock(blockFormat, charFormat);
                      cursor.insertText(QString::number(s.value));
                  
                      charFormat.setForeground(Qt::black);
                      charFormat.setFontPointSize(12);
                      cursor.insertBlock(blockFormat, charFormat);
                      cursor.insertText(QString::number(s.value / m_total * 100) + "%");
                  
                      text->setY(ellipse->boundingRect().center().y() - text->boundingRect().height()/2);
                      scene()->addItem(ellipse);
                  }
                  

                  and I remove that onMouseLeave: void PieView::onMouseLeave(){ scene()->removeItem(ellipse); }. PieView is the subclass of QGraphicsView.

                  EDIT
                  Will change that static to qobject cast later. Thanks for the reminder.

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

                  @Emon-Haque
                  Just one quickie: that pie chart/view does not use any QGraphicsItemGroup does it?

                  ? 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @Emon-Haque
                    Just one quickie: that pie chart/view does not use any QGraphicsItemGroup does it?

                    ? Offline
                    ? Offline
                    A Former User
                    wrote on last edited by A Former User
                    #12

                    @JonB, no, it doesn't use any group. In the PieView, QGriphicsView, constructor I initialize the ellipse and text AND PieView has a function makePie where I add slice. Here's the constructor:

                    PieView::PieView(QWidget *parent) : QGraphicsView(parent){
                        auto scene = new QGraphicsScene(this);
                        setScene(scene);
                        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
                        ellipse = new QGraphicsEllipseItem();
                        ellipse->setBrush(Qt::white);
                        ellipse->setPen(Qt::NoPen);
                        ellipse->setAcceptHoverEvents(false);
                        text = new QGraphicsTextItem(ellipse);
                        text->setAcceptHoverEvents(false);
                        connect(this, &PieView::mouseOver, this, &PieView::onMouseOver);
                        connect(this, &PieView::mouseLeave, this, &PieView::onMouseLeave);
                    }
                    

                    and here's makePie:

                    void PieView::makePie(QVector<PieSeries>& series){
                        scene()->clear();
                        m_total = 0;
                        float startAngle = 0, spanAngle;
                        for (int i = 0; i < series.size(); i++) m_total += series[i].value;
                        QRandomGenerator rand;
                        auto rect = QRectF(0,0, 200,200);
                        for (int i = 0; i < series.size(); i++){
                            spanAngle = series[i].value / m_total * 360;
                            auto color = QColor::fromRgb(rand.global()->bounded(0,255), rand.global()->bounded(0,255), rand.global()->bounded(0,255));
                            auto slice = new Slice(startAngle, spanAngle, color, rect, series[i]);
                            scene()->addItem(slice);
                            startAngle += spanAngle;
                        }
                        auto eRect = QRectF(QPoint(sceneRect().center().x() - 75, sceneRect().center().y() - 75), QSize(150,150));
                        ellipse->setRect(eRect);
                        text->setTextWidth(rect.width());
                    }
                    
                    1 Reply Last reply
                    0
                    • ? Offline
                      ? Offline
                      A Former User
                      wrote on last edited by A Former User
                      #13

                      Problem is the base calls. Probably, there's something in the base mouseReleaseEvent that created the issue. I've taken it back to the original state, removed base constructor, update and base::...Event calls and added an empty mouseReleaseEvent like this:

                      void Slice::mousePressEvent(QGraphicsSceneMouseEvent *e){
                          if(e->button() != Qt::LeftButton) return;
                          if(isSelected()) setSelected(false);
                          else setSelected(true);
                      }
                      void Slice::mouseReleaseEvent(QGraphicsSceneMouseEvent*){}
                      

                      Now it behaves normally:

                      x2.gif

                      One thing that I couldn't figure out yet is: when I first hover over a slice, rest of the slices are displaced. In the animation see, when mouse entered the bottom right slice for the first time, other two slices moved to the left! This happens only once with 3 slices. Why does it move?

                      Updated the github repo with these changes.

                      Pl45m4P 1 Reply Last reply
                      0
                      • ? A Former User

                        Problem is the base calls. Probably, there's something in the base mouseReleaseEvent that created the issue. I've taken it back to the original state, removed base constructor, update and base::...Event calls and added an empty mouseReleaseEvent like this:

                        void Slice::mousePressEvent(QGraphicsSceneMouseEvent *e){
                            if(e->button() != Qt::LeftButton) return;
                            if(isSelected()) setSelected(false);
                            else setSelected(true);
                        }
                        void Slice::mouseReleaseEvent(QGraphicsSceneMouseEvent*){}
                        

                        Now it behaves normally:

                        x2.gif

                        One thing that I couldn't figure out yet is: when I first hover over a slice, rest of the slices are displaced. In the animation see, when mouse entered the bottom right slice for the first time, other two slices moved to the left! This happens only once with 3 slices. Why does it move?

                        Updated the github repo with these changes.

                        Pl45m4P Offline
                        Pl45m4P Offline
                        Pl45m4
                        wrote on last edited by Pl45m4
                        #14

                        @Emon-Haque said in How do you handle selection of QGraphicsItem?:

                        when I first hover over a slice, rest of the slices are displaced. In the animation see, when mouse entered the bottom right slice for the first time, other two slices moved to the left! This happens only once with 3 slices. Why does it move?

                        This seem to be a miscalculation of your slice coordinates.
                        When you hover the slice, it moves a bit out of the pie chart and the rest seems to follow. So the whole pie moves by X to the right.
                        Can't tell where exactly but I would check the coordinates where the pie is drawn and how the relation between the "highlighted" (moved out) slice and the rest of the pie slices works.

                        Edit:

                        Or the whole pie "jumps" to the right in your scene to react on the geometry change... You need to test it. Do you center your pie in your scene?


                        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                        ~E. W. Dijkstra

                        ? 1 Reply Last reply
                        0
                        • Pl45m4P Pl45m4

                          @Emon-Haque said in How do you handle selection of QGraphicsItem?:

                          when I first hover over a slice, rest of the slices are displaced. In the animation see, when mouse entered the bottom right slice for the first time, other two slices moved to the left! This happens only once with 3 slices. Why does it move?

                          This seem to be a miscalculation of your slice coordinates.
                          When you hover the slice, it moves a bit out of the pie chart and the rest seems to follow. So the whole pie moves by X to the right.
                          Can't tell where exactly but I would check the coordinates where the pie is drawn and how the relation between the "highlighted" (moved out) slice and the rest of the pie slices works.

                          Edit:

                          Or the whole pie "jumps" to the right in your scene to react on the geometry change... You need to test it. Do you center your pie in your scene?

                          ? Offline
                          ? Offline
                          A Former User
                          wrote on last edited by
                          #15

                          @Pl45m4, at that time I didn't have the call setSceneRect(....). With that line, now it doesn't move.

                          1 Reply Last reply
                          1

                          • Login

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