PDA

View Full Version : Question about drag and drop in QGraphicsView



meazza
30th March 2011, 10:30
First of all hello to all fellow programmers. I am a new member so wanted to say hi first.

I am working with a little projekt to learn more about the graphicsscene, graphicsview and graphicsitem and how the work together. I have managed to create a graphicsview and graphicsscene and managed to add items to it using the mouse events.

Now what i want to do is to move these items i have added. And going crazy here. Been reading docs for 2 days now but havent really figured it out yet. I am a bit of a newbie at Qt so maybe thats why i cant grasp it.

Hopefully there are some helpfull people here that can help me out understanding this.

Also attached my code in a zip

Kind regards

high_flyer
30th March 2011, 10:40
And going crazy here
It would be helpful if you explain what you are going crazy about.
What are the SPECIFIC problems you have or don't understand.

meazza
30th March 2011, 10:47
The SPECIFIC problem i have is that i dont know how to make the items i add to the graphicsscene movable. So I can click on them and drag them with my mouse.

Have read somewhere to reimplement QGraphicsItem::dragEnterEvent(), QGraphicsItem::dragMoveEvent(), QGraphicsItem::dragLeaveEvent(), and QGraphicsItem::dropEvent() but dont quite understand how. Are there other ways?

high_flyer
30th March 2011, 10:53
but dont quite understand how.
You don't understand how - what?
Based on your text it sounds you don't know how to subclass or override a method - if this is the case, its not Qt but C++ question, which is off topic for this forum.
If its something else you don't understand, please be SPECIFIC about what your problem is, if you want help!

wysota
30th March 2011, 12:42
Your code has a lot of problems such as this:

void MainWindow::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QPen pen(Qt::gray, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);
ui->graphicsView->setScene(m_scene);
}
Adding items in mouse move events is probably a bad idea as well. Spaghetti code doesn't help too, try simplifying it.

As for your problem - if you want to make items movable, you don't need to use drag and drop, that's for something else. You can make items movable by setting the ItemIsMovable flag on the item and making sure the scene has a chance to process mouse events (that is if you reimplement mouse event handlers, be sure to call the base class implementation).

meazza
30th March 2011, 19:05
Your code has a lot of problems such as this:

void MainWindow::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QPen pen(Qt::gray, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen);
ui->graphicsView->setScene(m_scene);
}
Adding items in mouse move events is probably a bad idea as well. Spaghetti code doesn't help too, try simplifying it.

As for your problem - if you want to make items movable, you don't need to use drag and drop, that's for something else. You can make items movable by setting the ItemIsMovable flag on the item and making sure the scene has a chance to process mouse events (that is if you reimplement mouse event handlers, be sure to call the base class implementation).

I can understand that my code looks bad. I have just used it to try some stuff out and there are some stuff left that I am not using like the code you pointed out. But your explenation helps alot. I am gonna try so simplify it and set the flags to se if it works out. Thanks alot Zen Master :)

meazza
31st March 2011, 08:47
void Graphicsscene::mousePressEvent(QGraphicsSceneMouse Event *event)
{
if(figur == 1)
{
if (event->button() != Qt::LeftButton)
return;

QPolygonF myPolygon;
myPolygon << QPointF(-100, 0) << QPointF(0, 100)
<< QPointF(100, 0) << QPointF(0, -100)
<< QPointF(-100, 0);
QGraphicsPolygonItem *PolygonItem = new QGraphicsPolygonItem;
PolygonItem->setPolygon(myPolygon);
PolygonItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges);
PolygonItem->setPos(event->scenePos());
addItem(PolygonItem);
update();
figur = 0;
}
}

This code makes it possible to move the item around but have noticed that the are that you can click to move it around is very small. Is it possible to make it bigger? ex if i click on the figure so it moves it or something similar?

wysota
31st March 2011, 09:52
So where do you have to click for it to move?

meazza
31st March 2011, 10:52
I have to click on the edge of the item, and it has to be on the pixel. Very hard to click it with the mouse.

wysota
31st March 2011, 11:06
Apparently the inside of the item is empty. If simply setting a brush doesn't help you'll have to reimplement the shape() of the item.

meazza
31st March 2011, 11:18
I fixed it i think. I thought since i add the items during a pressEvent and when i tried to move the item i press the mouse so the pressEvent funktion was called hence not allowing me to move it. So added QGraphicsScene::mousePressEvent(mouseEvent); if iwas not adding items in the pressEvent.

Well it works now but do you find this a reasonable solution?

wysota
31st March 2011, 11:52
I don't think adding items in a mouse press event is a reasonable solution. I tend to lean towards more high-level solutions.

meazza
31st March 2011, 12:15
Well I am not a master of zen yet :D, but hopefully someday I will be. What would that high-level solution be? Just asking out of curiosity, not gonna try it out this time. Not high-level yet :).

Thanks for all your help

wysota
31st March 2011, 12:22
Like emitting a signal "hey, I want item to be added at these coordinates" and then handling it in a dedicated method that can be called from different contexts. And mousePress is probably a bad place to do it anyway, mouseRelease would be a better one.

liran ritkop
31st March 2011, 12:46
What about the solution of reimplement the function mouseMoveEvent()?
You can do something like that too:

void Object::mouseMoveEvent(QMouseEvent *event){
PolygonItem->move(event->x(),event->y());
}

wysota
31st March 2011, 12:48
Sure but why if you have the ItemIsMovable flag?

meazza
31st March 2011, 13:40
I have found another question. How do QWidgets behave in the graphicsscene? Do I need to use the QGraphicsProxyWidget to be able to move it or? Because i cant set flags to a normal QWidget.


Embedded *MyWidget = new Embedded();
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
proxy = addWidget(MyWidget);
proxy->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
proxy->setPos(mouseEvent->scenePos());
addItem(proxy);
figur = 0;

I tried this and it positions as i would like to but cant move it..Maybe I am waaaay out there on this one :)

wysota
31st March 2011, 14:07
I'd say you can't move it because the widget handles the event so it never reaches the scene code responsible for moving the item.