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
QtWS25 Last Chance

ItemClipsToShape doesn't work

Scheduled Pinned Locked Moved General and Desktop
9 Posts 3 Posters 3.6k Views
  • 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