Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    ItemClipsToShape doesn't work

    General and Desktop
    3
    9
    3178
    Loading More Posts
    • 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.
    • R
      Rhadel last edited by

      Hi,

      I have a custom QGraphicsItem class that paints some complexes figures into scene. I have re-implemented boudingRect() member in order to make suitable "click and drag" on these kind of items. But a QRectF is not enough accurate for the precision that I need in clicks.

      In my QGraphicsItem custom class I have the following sentences:

      @
      this->setFlag(QGraphicsItem::ItemClipsToShape, true);
      this->setFlag(QGraphicsItem::ItemIsMovable, true);
      @

      As I understand, ItemClipsToShape flag should replace the call "boundingRect()" to check if item has been clicked, for "shape" (that returns a QPaintPath) with the shape where I want to detect the click.

      Shape has been implemented correctly, to check it, I draw it and It's properly drawn in scene:
      @
      QPainterPath path = shape();
      painter->drawPath(path); //Properly drawn.
      @

      The problem: it seems like Qt is still calling "boundingRect()" to get the area that I want to use to check if item is clicked, even with the flag set.

      Any suggestions?

      1 Reply Last reply Reply Quote 0
      • raven-worx
        raven-worx Moderators last edited by

        sry, but reading your post the following is not clear to me: did you reimplement QGraphicsItem::shape() in your graphicsitem subclass?

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply Reply Quote 0
        • R
          Rhadel last edited by

          Yes, I did. It returns the shape that I want for click and collision.

          1 Reply Last reply Reply Quote 0
          • raven-worx
            raven-worx Moderators last edited by

            can you please post the code of the shape() and paint() method

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply Reply Quote 0
            • R
              Rhadel last edited by

              Sure:

              It returns the shape. Its a bit complicated method. Some lines build the entire item:

              @
              QPainterPath Cable::shape() const
              QPainterPath result;
              QLineF checkingLine(QPointF(0, 0), QPointF (1, 0));
              foreach (CableLine* course, lines){
              QLineF current(course->posx, course->posy);
              if (current.angleTo(checkingLine) == 0 || current.angleTo(checkingLine) == 180){
              QPointF init(current.p1().x(), current.p1().y() - 3);
              QPointF ending(current.p2().x(), current.p2().y() + 3);
              QRectF rect(init, ending);
              result.addRect(rect);
              continue;
              }
              if (current.angleTo(checkingLine) == 90 || current.angleTo(checkingLine) == 270){
              QPointF init(current.p1().x() - 3, current.p1().y());
              QPointF ending(current.p2().x() + 3, current.p2().y());
              QRectF rect(init, ending);
              result.addRect(rect);
              continue;
              }
              qDebug() << "Error condition";
              }
              result.setFillRule(Qt::OddEvenFill);
              return result;
              }
              @

              And paint:

              @
              void Cable::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
              {

              if (!painter) return;
              painter->save();
              
              //Draw connection arrow:
              QVector <QPointF> polyPoints;
              CableLine* line = lines.last();
              QLineF last(line->posx, line->posy);
              
              polyPoints.append(QPointF(last.x2() - _ARROW_CABLE_WIDTH/2, last.y2()));
              polyPoints.append(QPointF(last.x2() + _ARROW_CABLE_WIDTH/2, last.y2()));
              polyPoints.append(QPointF(last.x2(), last.y2() + _ARROW_CABLE_HEIGHT));
              QPolygonF poly(polyPoints);
              painter->drawPolygon(poly);
              
              
              painter->restore();
              

              }
              @

              1 Reply Last reply Reply Quote 0
              • raven-worx
                raven-worx Moderators last edited by

                are you sure you want to use Qt::OddEvenFill fill rule instead of Qt::WindingFill ?
                Nevertheless i couldn't spot any problem in your code on first glance.

                But whats exactly the problem? That boundingRect() is called at all? Or that you receive mouse events even outside the shape?

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

                1 Reply Last reply Reply Quote 0
                • R
                  Rhadel last edited by

                  No. The problem is that I want to use shape() instead boundingRect() in order to captura click events.

                  I tried with Qt::WindingFill, with the same resutl, and I setted this->setFlag(QGraphicsItem::ItemClipsToShape, true).

                  Even so, click event is only called inside the boundingRect() rectangle, but It's not the exactly area that I want the item to reply to such event. It's the shape area intead.

                  Shape area is correctly, because when I draw it in paint method, I can see correctly filled and drawn.

                  Thank you for you reply.

                  1 Reply Last reply Reply Quote 0
                  • R
                    Rhadel last edited by

                    I have some troubles with mapTo.

                    When shapes colliding, I enter a function: "collisionProduced". But, by calling mapToScene, the shape seems being displaced to left. How it comes? I just changed the coordinate system in order to obtain the coords in scene system, not moving the shape.

                    1 Reply Last reply Reply Quote 0
                    • J
                      JLin last edited by

                      I had same problem. My item is a circle icon, the boundingRect is a square. Clicks within the square but outside the circle area triggers mouse events. I fixed it by defining shape() as constant method, which overrides the parent::shape() const instead of overloading another shape().
                      @
                      QPainterPath shape() const;
                      @

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post