如何更改 Qt 的默认选择行为?

How to change Qt's default selection behavior?

我是 QGraphicsView 的新手。所以出于练习的目的,我画了一些形状,如矩形、椭圆、多边形、折线、文本等。
我在这里观察到,每当我们单击这些绘制的对象时(select 使用鼠标单击它们)
对象周围出现虚线矩形,表示对象已 selected.
如果我想改变 Qt 的 selection 的默认行为,该怎么做?

I do not want dotted rectangle around circle, when it will be clicked by mouse, but that dots should be around its circumference.

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QStyleOptionGraphicsItem>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

public:
    virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
#endif // WIDGET_H   

widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include<QGraphicsScene>
    #include<QGraphicsView>
    #include<QGraphicsEllipseItem>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        QGraphicsScene *scene = new QGraphicsScene(this);
    
        QGraphicsView *view = new QGraphicsView(this);
    
        QGraphicsEllipseItem *ellipse = new QGraphicsEllipseItem();
        ellipse = scene->addEllipse(2,2,80,80);
        //ellipse->setFlag(QGraphicsItem::ItemIsSelectable);
        scene->addItem(ellipse);
    
        view->setScene(scene);
        ui->verticalLayout->addWidget(view);
    
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    
    void Widget :: paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
            auto copied_option = *option;
            copied_option.state &= ~QStyle::State_Selected;
            auto selected = option->state & QStyle::State_Selected;
            paint(painter, &copied_option, widget);
            if (selected) {
                QPainterPath path;
                path.addEllipse(2,2,80,80);
                painter->save();
                painter->setBrush(Qt::NoBrush);
                painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
                painter->drawPath(path);
                painter->restore();
      }
}

据我所知,没有任何 'built in' 设施可以满足您的需求。在当前 code base 你会看到...

void QGraphicsEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                                 QWidget *widget)
{
    Q_D(QGraphicsEllipseItem);
    Q_UNUSED(widget);
    painter->setPen(d->pen);
    painter->setBrush(d->brush);
    if ((d->spanAngle != 0) && (qAbs(d->spanAngle) % (360 * 16) == 0))
        painter->drawEllipse(d->rect);
    else
        painter->drawPie(d->rect, d->startAngle, d->spanAngle);
    if (option->state & QStyle::State_Selected)
        qt_graphicsItem_highlightSelected(this, painter, option);
}

所以选择状态指示器是由 qt_graphicsItem_highlightSelected 绘制的,它直接从 paint 方法调用。 qt_graphicsItem_highlightSelected 本身只是设置了一些基本参数,并以绘制虚线矩形边框结束。

替换默认行为的明显方法是子 class 感兴趣的 QGraphicsItem class 并覆盖 paint 成员(未经测试)...

#include <QApplication>
#include <QGraphicsEllipseItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPainter>
#include <QStyleOptionGraphicsItem>

class ellipse: public QGraphicsEllipseItem {
public:
    explicit ellipse (qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = nullptr)
        : QGraphicsEllipseItem(x, y, width, height, parent)
        {}
    virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
    {
        auto copied_option = *option;
        copied_option.state &= ~QStyle::State_Selected;
        auto selected = option->state & QStyle::State_Selected;
        QGraphicsEllipseItem::paint(painter, &copied_option, widget);
        if (selected) {
            painter->save();
            painter->setBrush(Qt::NoBrush);
            painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
            painter->drawPath(shape());
            painter->restore();
        }
    }
};

int main (int argc, char **argv)
{
  QApplication app(argc, argv);
  QGraphicsView view;
  QGraphicsScene scene;
  view.setScene(&scene);
  ellipse e(2, 2, 80, 80);
  e.setFlag(QGraphicsItem::ItemIsSelectable);
  scene.addItem(&e);
  view.show();
  return app.exec();
}