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. ItemClipsToShape doesn't work
Qt 6.11 is out! See what's new in the release blog

ItemClipsToShape doesn't work

Scheduled Pinned Locked Moved General and Desktop
9 Posts 3 Posters 4.5k 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.
  • R Offline
    R Offline
    Rhadel
    wrote on last edited by
    #1

    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
    0
    • raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      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
      0
      • R Offline
        R Offline
        Rhadel
        wrote on last edited by
        #3

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

        1 Reply Last reply
        0
        • raven-worxR Offline
          raven-worxR Offline
          raven-worx
          Moderators
          wrote on last edited by
          #4

          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
          0
          • R Offline
            R Offline
            Rhadel
            wrote on last edited by
            #5

            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
            0
            • raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by
              #6

              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
              0
              • R Offline
                R Offline
                Rhadel
                wrote on last edited by
                #7

                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
                0
                • R Offline
                  R Offline
                  Rhadel
                  wrote on last edited by
                  #8

                  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
                  0
                  • J Offline
                    J Offline
                    JLin
                    wrote on last edited by
                    #9

                    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
                    0

                    • Login

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