PDA

View Full Version : how to use mouse move event to drag curves on QGraphicsScene?



sarbh20ss
17th September 2013, 07:23
hey I am drawing a bezier curve on QGraphicsScene.
Initialy I was drawing curve using path and drawing it in pixmap and then adding pixmap to scene.
This allows me to add multiple paths to scene through pixmap.



drawGlyphs=new QPixmap(800, 800);
drawGlyphs->fill(Qt::white);
QPainter p(drawGlyphs);
p.setViewport(50,200,400,400);
p.setPen(Qt::black);
p.drawPath(mypath);
pScene->addPixmap(*drawGlyphs);


I wanted to check if the mouse click is on one of the paths. But with above structure I couldn't do that.
So I subclass QGraphicsPathItem.



class mySubClass1 : public QGraphicsPathItem
{
public:
mySubClass1();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
}


Here I am drawing curve in painter path, setting this path to object of 'mySubClass1' and adding this object as item to scene.
Now when I try to implement mouse move event I could not detect on which point which is on the curve I clicked and trying to drag.

How do I solve this problem?
Is the structure of my program correct?

high_flyer
17th September 2013, 10:01
can you show the content of your mosuePressEvent() override?

sarbh20ss
17th September 2013, 13:28
My implementation of mousePressEvent is:



void mySubClass1::mousePressEvent(QGraphicsSceneMouseEv ent *event)
{
if(event->button() == Qt::LeftButton)
{
qDebug()<<"in musubclass mouse press event: "<<event->pos().x()<<" "<<event->pos().y();
if(shape().contains(event->pos()))
{
currPosX=event->pos().x();
currPosY=event->pos().y();
qDebug()<<"currPosX currPosY: "<<currPosX<<" "<<currPosY;
}
}
}

high_flyer
18th September 2013, 12:58
And? do you get the debug message?

sarbh20ss
19th September 2013, 05:54
Well sorry but did not get you...

I have attached my complete program. I actually want to detect the mouse click at particular point and mouse move for same point.
Hope you will help solve me this problem.

high_flyer
19th September 2013, 08:39
Well sorry but did not get you...
What exactly didn't you get? how can I make my question any simpler?

sarbh20ss
19th September 2013, 09:48
I am drawing a path on scene using an object of subclass of QGraphicsPathItem. At particular points on this path I want to detect the mouse click and mouse move event.
According to current coordinates of mouse pointer given by mouse move event I want to redraw this path.
In a program that I have attached in previous post I am able to detect the press event but want to check if click is on those particular points. If yes then using move event I want to redraw it. But I am not able to understand how to pass these new coordinates to a function which generates this path.
So How to do that?

wysota
19th September 2013, 10:28
In my opinion your approach makes completely no sense. You should have items for nodes and separate items for curves (or lines) between nodes and manipulate curves using those node items. But you can't implement it in 10 lines of code no matter how much you try it. Trying to detect control points for curves by observing coordinates is a totally bogus approach in an object oriented system such as Graphics View.

Don't take it personal but it's more and more often situation that I'm surprised people start programming without thinking first how they are going to implement the whole solution (in terms of designing the architecture, not writing the actual code) and they end up trying to implement some wacky solutions instead of using standard approaches used by everyone else in the industry. For instance -- how did you plan to move the control point in the path to some other position?

sarbh20ss
19th September 2013, 12:23
Well I will not take it personally.
Can you advice me where I can study or get to know the 'standard approaches in industry' for Graphics related coding or how to design architecture for such type of Graphics coding.

I was thinking of implementing mouse move event of QGraphicsPathItem.

Appreciate your advice on showing me the right way.

wysota
19th September 2013, 12:59
Can you advice me where I can study or get to know the 'standard approaches in industry' for Graphics related coding or how to design architecture for such type of Graphics coding.
Look at standard programs -- Photoshop, Gimp, Corel Draw, Autocad, etc. etc. Think how they might be implementing the functionality they offer.


I was thinking of implementing mouse move event of QGraphicsPathItem.
Great, and what would you put in that event?


Appreciate your advice on showing me the right way.
I already told you in the previous post what in my opinion is the right way.

kamre
19th September 2013, 16:56
You should have items for nodes and separate items for curves (or lines) between nodes and manipulate curves using those node items.
Do you mean that something like this can be used:

#include <QtWidgets>

class Path;

class Node: public QGraphicsEllipseItem {
public:
Node(Path* path, int index);
protected:
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
static const qreal rad;
Path* path;
int index;
};

const qreal Node::rad = 5;

class Path: public QGraphicsPathItem {
public:
Path(const QPainterPath& path, QGraphicsScene* scene);

void updateElement(int index, const QPointF& pos);
private:
QPainterPath path;
};

Node::Node(Path* path, int index)
: QGraphicsEllipseItem(-rad, -rad, 2*rad, 2*rad),
path(path) , index(index)
{
setZValue(1);
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
setBrush(Qt::green);
}

QVariant Node::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange) {
path->updateElement(index, value.toPointF());
}
return QGraphicsEllipseItem::itemChange(change, value);
}

Path::Path(const QPainterPath& path, QGraphicsScene* scene)
: QGraphicsPathItem(path), path(path)
{
for (int i = 0; i < path.elementCount(); ++i) {
auto node = new Node(this, i);
node->setPos(path.elementAt(i));
scene->addItem(node);
}
setPen(QPen(Qt::red, 1.75));
}

void Path::updateElement(int index, const QPointF &pos)
{
path.setElementPositionAt(index, pos.x(), pos.y());
setPath(path);
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPainterPath path;
path.moveTo(0, 0);
path.cubicTo(-30, 70, 35, 115, 100, 100);
path.lineTo(200, 100);
path.cubicTo(200, 30, 150, -35, 60, -30);
auto scene = new QGraphicsScene();
scene->addItem(new Path(path, scene));
auto view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing);
view->resize(600, 400);
view->show();
return app.exec();
}
?

wysota
19th September 2013, 22:00
I don't have a ready answer for every problem. What you suggested seems reasonable but I can't say whether it is a good approach or not. You need to think whether it satisfies your requirements or not.