PDA

View Full Version : Custom QGraphicsLineItem



darktorres
5th November 2014, 02:56
I'm developing a medical image viewer and need to be able to draw lines and angles over the image and put the length or angle in a table. In the image is what I have done.
10732
To make the components of the line move together (red squares, green line and text) I made the green line the parent of the other objects to group them. This works, more or less. What I need to do now is make the line resizable if the user drags the red squares, store the row/column of the table to be able to update the value in the table on line resize and other stuff, like reimplementing shape() and boundingRect(). I subclassed QGraphicsItem but lots of things went wrong, like I click on a place and the line is made on another place (as if there was a offset), there was a black line painted over the green line and other things. Here is my subclass:


#ifndef MYITEM_H
#define MYITEM_H

#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>

class MyLine : public QGraphicsItem
{
public:
MyLine(int tableRow, int tableColumn);

QRectF boundingRect() const;

void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget);
QPainterPath shape() const;

bool Pressed;
QGraphicsLineItem *line1;
QGraphicsLineItem *point1;
QGraphicsLineItem *point2;
qint32 tableRow;
qint32 tableColumn;

protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

};

#endif // MYITEM_H



#include <QDebug>
#include "myline.h"

MyLine::MyLine(int tableRow, int tableColumn)
{
qDebug() << "MyLine ctor";
this->tableRow = tableRow;
this->tableColumn = tableColumn;

Pressed = false;
// setFlag(ItemIsMovable);
// setFlag(ItemIsSelectable);
setFlag(ItemIgnoresTransformations);

point1 = new QGraphicsLineItem(QLineF(scenePos(), scenePos()), this);

line1 = 0;
point2 = 0;
}

QRectF MyLine::boundingRect() const
{

return childrenBoundingRect();
}

void MyLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
// qDebug() << "MyLine paint";

QRectF rect = boundingRect();

if(Pressed)
{
if(line1 != 0){
painter->setPen(QPen(Qt::blue, 3));
painter->drawLine(line1->line());
}
painter->setPen(QPen(Qt::red, 3));
painter->drawLine(point1->line());
if(point2 != 0){
painter->setPen(QPen(Qt::red, 3));
painter->drawLine(point2->line());
}
}
else
{
if(line1 != 0){
painter->setPen(QPen(Qt::green, 3));
painter->drawLine(line1->line());
}
painter->setPen(QPen(Qt::red, 3));
painter->drawLine(point1->line());
if(point2 != 0){
painter->setPen(QPen(Qt::red, 3));
painter->drawLine(point2->line());
}
painter->setPen(QPen(Qt::white, 3));
painter->drawRect(rect);
}
}

QPainterPath MyLine::shape() const
{
QPainterPath path;
if(line1 != 0){
path.addRect(line1->boundingRect());
qDebug() << "shape line1: " << line1->boundingRect();
}
if(point1 != 0){
path.addRect(point1->boundingRect());
qDebug() << "shape point1: " << point1->boundingRect();
}
if(point2 != 0){
path.addRect(point2->boundingRect());
qDebug() << "shape point2: " << point2->boundingRect();
}
path.addRect(QRect(0, 0, 3, 3));
qDebug() << "path boundrect: " << path.boundingRect();
return path;
}

void MyLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "MyLine Press";
Pressed = true;
update();
QGraphicsItem::mousePressEvent(event);
}

void MyLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "MyLine Move";

qDebug() << "Event pos: " << event->pos();
qDebug() << "Event scenePos: " << event->scenePos();
qDebug() << "Event screenPos: " << event->screenPos();
qDebug() << "Event mapToParent: " << mapToParent(event->pos());
qDebug() << "Event mapToScene: " << mapToScene(event->pos());

if(Pressed){
prepareGeometryChange();
if(line1 == 0){
qDebug() << "No line1";
line1 = new QGraphicsLineItem(QLineF(point1->line().p1(), event->scenePos()), this);
}
if(line1 != 0){
qDebug() << "Line1, update!";
line1->line().setP2(event->scenePos());
}
}
update();
QGraphicsItem::mouseMoveEvent(event);
}

void MyLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "MyLine Release";

prepareGeometryChange();

if(line1 != 0){
if(line1->line().p1() == event->scenePos()){
qDebug() << "line1 length 0";
}
else{
qDebug() << "Made point2";
point2 = new QGraphicsLineItem(QLineF(line1->line().p2(), line1->line().p2()), this);
}
}

setFlag(ItemIsMovable);
setFlag(ItemIsSelectable);

Pressed = false;
update();
QGraphicsItem::mouseReleaseEvent(event);
}


Is there something I am doing wrong on this subclass or should I be doing something else?

wysota
5th November 2014, 08:11
In my opinion your boundingRect implementation is incorrect. Your paint implementation is likely wrong as well. I have no idea why you are trying to draw lines of your child items in your own paint method.