Skip to content
  • 0 Votes
    2 Posts
    585 Views
    eyllanescE

    boundingRect does not depend on the position of the item with respect to the scene since it is in coordinates with respect to the item. I recommend you review https://doc.qt.io/qt-5/graphicsview.html so that you understand the different coordinate systems that are handled.

  • 0 Votes
    2 Posts
    868 Views
    mrjjM

    Hi
    I just keep a pointer to the "white lines" and adjust if i move yellow.

    class ColorItem : public QGraphicsItem { .. ConnectorLine* line = nullptr; .. protected: QVariant itemChange(GraphicsItemChange change, const QVariant& value) override { if (change == ItemPositionChange && scene()) { if (line) { line->adjust(); } } return QGraphicsItem::itemChange(change, value); } private: QColor color; };

    line->Adjust() alters its endpoints. You could just adjust it directly here.

  • 0 Votes
    9 Posts
    3k Views
    U

    @mrjj i think i'll just write the code :p will do tomorrow and see what i get, thanks!

  • 0 Votes
    2 Posts
    3k Views
    Chris KawaC

    It would be nice to say what self and event are. I'm guessing a QGraphicsItem and a parameter of QGraphicsSceneMouseEvent? Is that right?

    If so then event.pos() and event.scenePos() are not exchangeable. The first one is cursor position in item's coordinates and the second one cursor position in scene coordinates. They are the same only when item is placed at (0,0). If item is moved they will differ. It's important to note that these values are what they were at the time the event took place, which might be different from the "current" values for item (this is a good thing). For example if you move your mouse fast and there are a lot of events generated the cursor position in these events will be a little behind the actual current position of the cursor before they "catch up".

    As for self.scenePos() - this is the position of the item in the scene. This is the point relative to which the event.pos() is calculated. It is not necessary the top left of the bounding rect. It can be placed anywhere using 'setTransformOriginPoint()'. It is often set to the center of the item. For example if you have a bunch of draggable circles a center is probably more convenient than a top left corner. For vertical bars on a chart the origin might be placed at the middle bottom of a bar etc.

  • 0 Votes
    11 Posts
    4k Views
    H

    @Asperamanca

    No, I didn't set these two flags ItemClipsToShape, ItemClipsChildrenToShape.

    Then I tried setting only one flag ItemClipsToShape, and both of ItemClipsToShape, ItemClipsChildrenToShape. For each, it still check if the point is in the boundingrect() firstly, and then check the shape() which means if point is not in boundingrect(), it wouldn't bother to check shape().

    So now my solution is still enlarging the boundingrect() area.

  • 1 Votes
    5 Posts
    3k Views
    A

    @Joel-Bodenmann
    To elaborate on your answer: The boundingRect() must include every pixel that you intend to paint to in your own item's paint method. That includes e.g. pixels that are outside your item proper, but painted to due to a wide pen.
    (Calculating the correct boundingRect for items with wide cosmetic pens can be a real pain.)

  • 0 Votes
    4 Posts
    1k Views
    Joel BodenmannJ

    That's exactly what I have been looking for! I definitely searched for the wrong terms.
    Thank you for your help. Very appreciated.

  • 0 Votes
    10 Posts
    5k Views
    C

    @egan

    Well, I re-implemented the whole mouse moving the puzzle shape thing. I am not using itemChanged() override anymore. The fact that the item's position x and y was not the same as the boundingRect().topLeft() x and y after rotating was an issue that was too problematic. A tangram shape; a right triangle with a hypotenuse that equaled the leg * the square root of 2 being contained by a bounding rectangle during rotation produced too many effects. So, I got it working, and very well, but I ended up using

    void PuzzlePiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QRectF rect = scene()->sceneRect(); float mx = event->scenePos().x() - xbeta; float my = event->scenePos().y() - ybeta; setTangramPositionAndShape(); \\ sets the boundingRect to the bounds of the actual polygon points if(rect.contains(boundingRect())) { setPos(mx, my); setTangramPositionAndShape(); } }

    And yes, the shape stops moving when it goes out of the scene, but a mouseDown sets it position back inside the scene and all is good.

    I made a tangram puzzle application way back when I was a young man. I used Cocoa/Objective C on a Mac. The thing was downloaded over 8 million times in a week. People from Japan would call me up and ask me about it. It was crazy. And yeah, it was free, so I am not a millionaire; my wife yelled at me for weeks for making it free. It was this small window about the size of an smart phone screen.

    Cocoa does not have a simple implementation to make an graphic item movable with some easy setFlag(QGraphicsItem::ItemIsMovable). It was much more difficult to implement back then. So, I am basically using the same bounds checking and resetting the object the same way as I did 25 years ago.

    My son is about to go to college for software engineering. I am teaching C++ with the implementation of this simple puzzle.

    Thanks for your help. Your posts kept me thinking!

    Craig