Search code examples
qtqt5qgraphicsitem

QGraphicsItem selection on opaque area


I have these flags set on a QGraphicsPixmapItem:

setFlag(QGraphicsItem::ItemIsMovable, true)
setFlag(QGraphicsItem::ItemIsSelectable, true);

When I click and move the item, I want the selection dotted lines to be highlighting the opaque area of the item only and not include the transparent background.

Current behavior - On click - dotted lines surround the Item in a rectangle:

enter image description here

Desired behavior - dotted lines surround the diamond.

How do I do this?


Solution

  • The following method only works when the image has a transparent external part as shown in the following part:

    enter image description here

    The solution is to overwrite the paint() method and draw the shape().

    #include <QApplication>
    #include <QGraphicsView>
    #include <QGraphicsPixmapItem>
    #include <QStyleOptionGraphicsItem>
    
    class GraphicsPixmapItem: public QGraphicsPixmapItem{
    public:
        GraphicsPixmapItem(const QPixmap & pixmap, QGraphicsItem * parent = 0): QGraphicsPixmapItem(pixmap, parent){
            setFlag(QGraphicsItem::ItemIsMovable, true);
            setFlag(QGraphicsItem::ItemIsSelectable, true);
        }
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *){
            painter->setRenderHint(QPainter::SmoothPixmapTransform, (transformationMode() == Qt::SmoothTransformation));
            painter->drawPixmap(offset(), pixmap());
            if (option->state & QStyle::State_Selected){
                painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
                painter->setBrush(Qt::NoBrush);
                painter->drawPath(shape());
            }
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsView w;
        QGraphicsScene scene;
        GraphicsPixmapItem *item = new GraphicsPixmapItem(QPixmap(":/image.png"));
        scene.addItem(item);
        w.setScene(&scene);
        w.show();
    
        return a.exec();
    }
    

    The complete example can be found in the following link.

    enter image description here