PDA

View Full Version : elastic node re-engineering



sajis997
4th August 2011, 18:39
Hello forum,


I am playing around with the elastic node example and have the some issue to discuss with:


When the scene loads the nodes are already connected with edges and i want to change this attribute. The edge will be connected with two adjacent nodes in the following manner:

1. When the user move the cursor over one of the adjacent nodes and press the Ctrl modifier and the nodes gets highlighted and remains highlighted as long as the Ctrl button is pressed while the cursor is over the node.

2. When the user move the mouse cursor while the Ctrl button is pressed down , the edge arrow will be drawn from the source node. And When the user cursor reach any of the destination node , the edge arrow will finish drawing at the destination node.

Initially , I did the following changes inside the node class :


1. Inside the constructor , i have set the



setAcceptHoverEvents(true);


I am having trouble with the highlighting effect. I have over-ridden the following functions:





//the following events are for the items visual appearance
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
//addded by sajjad
void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);



And the definition is as follows:




/////////////////////////////////////////

void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mousePressEvent(event);
}
void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mouseReleaseEvent(event);
}
void Node::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if(event->modifiers() == Qt::ControlModifier)
{
update();
QGraphicsItem::hoverMoveEvent(event);
}
}
void Node::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
if(event->modifiers() == Qt::ControlModifier)
{
update();
QGraphicsItem::hoverEnterEvent(event);
}
}
void Node::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{

update();
QGraphicsItem::hoverMoveEvent(event);
}


/////////////////////////////////////////////

And the nodes paint function is also updatd:


/////////////////////////////////////////////////////////////////



void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-7, -7, 20, 20);
QRadialGradient gradient(-3, -3, 10);
if (option->state & QStyle::State_Sunken)
{
//button pressed mode
gradient.setCenter(3, 3);
gradient.setFocalPoint(3, 3);
gradient.setColorAt(1, QColor(Qt::yellow).light(120));
gradient.setColorAt(0, QColor(Qt::darkYellow).light(120));
//gradient.setColorAt(0, QColor(Qt::red).light(120));
//qDebug() << "Sunken state" << endl;
std::cout << "It is in the sunken state" << std::endl;
}
else if(option->state & QStyle::State_MouseOver)
{
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::darkYellow);
std::cout << "It is in the mosue over state" << std::endl;
}
else if(option->state & (!QStyle::State_Sunken & QStyle::State_MouseOver))
{
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow);
}
else
{
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow);
std::cout << "It is in the initial state" << std::endl;
}
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 0));
painter->drawEllipse(-10, -10, 20, 20);
}



//////////////////////////////////////////////////////////////////


When i press the mouse button over a node , it sunken and the view is updated , but when i release the button , the node gets highlighted which should not happen. Node will only be highlighted only when the Ctrl modifier will be pressed.

If my explanation is not clear enough, please ask me for further elaboration.

I need some hint to resolve the issue.



Regards
Sajjad

wysota
4th August 2011, 19:10
What you want goes far beyond the architecture of elastic nodes example and using hover events is likely a wrong approach to the problem. Instead of focusing on painting, you should focus on data. Painting only presents the data. Currently you are trying to implement logic inside painting, this doesn't make much sense. If you want something done on Ctrl key then override keyPressEvent for something that has focus and can accept a key event (like the scene or the view). There manipulate your data and let it update its visual representation based on its logical representation and not based on the current state of the environment around it (like the position of the mouse pointer).

sajis997
5th August 2011, 12:14
What you want goes far beyond the architecture of elastic nodes example and using hover events is likely a wrong approach to the problem. Instead of focusing on painting, you should focus on data. Painting only presents the data. Currently you are trying to implement logic inside painting, this doesn't make much sense. If you want something done on Ctrl key then override keyPressEvent for something that has focus and can accept a key event (like the scene or the view). There manipulate your data and let it update its visual representation based on its logical representation and not based on the current state of the environment around it (like the position of the mouse pointer).

Thanks for the useful suggestion, i shall look into this. It will get easier to follow if you can forward me to any existing Qt application where it has something which is i am trying to achieve.

It seems that you have already gone through and solved the issue. Can you provide me with the link of such application having this behavior ?


Thanks
Sajjad

wysota
5th August 2011, 13:47
I don't have such an application at hand, I just know how things work inside Qt and how some things should be implemented. There is no single example you can base your work on. If you have specific problems, we'll help you to solve them. Now it's important to get your thinking on the right track.

sajis997
5th August 2011, 23:46
What you want goes far beyond the architecture of elastic nodes example and using hover events is likely a wrong approach to the problem.

Should i go for mouseMoveEvent() instead. Mouse Move Event is only functional when the left mouse button is hold down unless we declare the mouse tracking is switched on. I can switch it on inside the constructors. Now i need the Ctrl modifier. And i was thinking of using the modifier inside the mouseMoveEvent. In that case do we need to over-ride the keyPressEvent() ? I am not sure how to define the mouse modifier inside the keyPressEvent().



Instead of focusing on painting, you should focus on data. Painting only presents the data.

So i should move the data conditions inside the data() function instead


Currently you are trying to implement logic inside painting, this doesn't make much sense. If you want something done on Ctrl key then override keyPressEvent for something that has focus and can accept a key event (like the scene or the view).

Sorry, i believe that i misunderstood . Did you mean to over-ride the keyPressEvent() for the view or the item instead?


Hope to hear more from you about this issue.


Thanks
Sajjad

wysota
6th August 2011, 00:05
Should i go for mouseMoveEvent() instead. Mouse Move Event is only functional when the left mouse button is hold down unless we declare the mouse tracking is switched on. I can switch it on inside the constructors. Now i need the Ctrl modifier. And i was thinking of using the modifier inside the mouseMoveEvent. In that case do we need to over-ride the keyPressEvent() ? I am not sure how to define the mouse modifier inside the keyPressEvent().
It's one or the other. The choice is yours to make -- you can check the state of key modifiers in mouse events or check the mouse cursor position in key events.



So i should move the data conditions inside the data() function instead
You should add the concept of state to your object. Painting will reflect the current state.


Sorry, i believe that i misunderstood . Did you mean to over-ride the keyPressEvent() for the view or the item instead?
There is no single correct way of solving a problem. I would probably override events for the view or the scene (depending on the detailed behaviour I'd want) instead of the item.