I am new to QGraphicsView. So for the practice purpose I was drawing some shapes like Rectangle, Ellipse, Polygon, Polyline, Text etc.
I observed here that, whenever we click on these drawn objects ( select them using mouse click )
dotted line rectangle appears around the object which indicates that, object is selected.
If I want to change that Qt's default behavior of selection, how to do that ?
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();
}
}
CodePudding user response:
As far as I'm aware there isn't any 'built in' facility to fo what you want. In the current code base you'll see...
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);
}
So the selection status indicator is drawn by qt_graphicsItem_highlightSelected
which is called directly from the paint
method. qt_graphicsItem_highlightSelected
itself simply sets up a few basic parameters and ends by drawing the dashed rectangular border.
The obvious way to replace the default behaviour would be to subclass the QGraphicsItem
class of interest and override the paint
member (untested)...
#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();
}