1 Attachment(s)
QGraphicsView move item issues.
Hello,
I am new to deveopment with Qt and are currently developing a simple application which let's you create graphical representation of a scene (e.g. a room) with a transmitter and several sensors. I use the QGraphics framework for this task. The "scene edge" is represented by a class derived from QGraphicsRectItem. The transmitter class is derived from QGraphicsEllipseItem and the sensors are derived from QGraphicsPolygonItem. All these objects and the QGraphicsView/QGraphicsScene are part of the UIInputSceneWidget.
I was at a point where I was able to move items separately. I.e. the item under the mouse cursor was moved, when you click, hold and move. But now that I moved a few functions around it doesn't work any more and I cannot figure out why.
There are two possibilities what happens:
1. If I move the scene edge (QGraphicsRectItem) before adding the transmitter or the sensors, then this rectangle is moved wherever I click, hold and move in the QGraphicsView. The rectangle "jumps" under the cursor as soon as I move the mouse. Even if I click outside the rectangle this happens.
2. If I do not move the rectangle before adding the transmitter or the sensors, then I can only move the first item that I added (either the transmitter or the first sensor). This item also "jumps" under the cursor as soon as I click, hold and move on a point in the view.
Here is the code that I suppose is relevant. Please ask for more if this is not sufficient:
Code:
class UIInputSceneWidget
: public QWidget{
Q_OBJECT
public:
[...]
signals:
[...]
private slots:
void insertFinished();
void insertSceneEdge(UISceneEdge *newSceneEdge);
[...]
private:
UIGraphicsScene *scene;
UIGraphicsView *view;
UISceneEdge *sceneEdge;
UITransmitter *transmitter;
QVector<UISensor *> sensors;
[...]
};
void UIInputSceneWidget::insertFinished()
{
if (scene->getMode() == UIGraphicsScene::InsertEdge)
scene->setMode(UIGraphicsScene::MoveItem);
}
void UIInputSceneWidget::insertSceneEdge(UISceneEdge *newSceneEdge)
{
if (sceneEdge == NULL) {
sceneEdge = newSceneEdge;
} else {
delete newSceneEdge;
return;
}
// stuff regarding buttons which is not important here
}
{
if ((sceneEdge == NULL) || !(sceneEdge->pointIsInsideSceneEdge(mouseEvent->scenePos())))
return;
UISensor *newSensor = new UISensor(mouseEvent->scenePos(), sceneEdge);
sensors.push_back(newSensor);
str.setNum(sensors.size());
sensorLineEdit->setText(str);
}
{
if ((sceneEdge == NULL) || !(sceneEdge->pointIsInsideSceneEdge(mouseEvent->scenePos())))
return;
UITransmitter *newTransmitter = new UITransmitter(mouseEvent->scenePos(), sceneEdge);
transmitter = newTransmitter;
transmitterButton->setChecked(false);
transmitterButton->setEnabled(false);
scene->setMode(UIGraphicsScene::MoveItem);
setTransmitterLocationLabel();
}
Code:
{
Q_OBJECT
public:
enum Mode { InsertEdge, InsertTransmitter, InsertSensor, MoveItem };
void setMode(Mode mode);
[...]
signals:
void insertFinished();
void insertSceneEdge(UISceneEdge *sceneEdge);
[...]
protected:
private:
Mode myMode;
};
{
if (myMode == InsertEdge) {
qreal x1 = firstPointOfSceneEdge.x();
qreal x2 = mouseEvent->scenePos().x();
qreal y1 = firstPointOfSceneEdge.y();
qreal y2 = mouseEvent->scenePos().y();
if (x1 < x2) {
topLeft.setX(x1);
bottomRight.setX(x2);
} else {
topLeft.setX(x2);
bottomRight.setX(x1);
}
if (y1 < y2) {
topLeft.setY(y1);
bottomRight.setY(y2);
} else {
topLeft.setY(y2);
bottomRight.setY(y1);
}
emit setSceneSize
(QRectF(topLeft, bottomRight
));
} else if (myMode == MoveItem) {
emit moveEvent(); /* for updating labels and stuff */
}
}
{
if (mouseEvent->button() != Qt::LeftButton)
return;
switch (myMode) {
case InsertEdge: {
firstPointOfSceneEdge = mouseEvent->scenePos();
UISceneEdge
*sceneEdge
= new UISceneEdge
(QRectF(firstPointOfSceneEdge,
firstPointOfSceneEdge));
addItem(sceneEdge);
emit insertSceneEdge(sceneEdge);
emit setSceneSize
(QRectF(firstPointOfSceneEdge,
firstPointOfSceneEdge));
break;
}
case InsertSensor: {
/* The sensor cannot be inserted directly because the pointer to
* the sceneEdge is not stored in this object, but in
* UIInputWidget. Let that object create and add the sensor. */
emit insertSensor(mouseEvent);
break;
}
case InsertTransmitter: {
/* Same reason as above! */
emit insertTransmitter(mouseEvent);
break;
}
default:
;
}
}
{
emit insertFinished();
}
UIGraphicsView is derived from QGraphicsView and just reimplements keyPressEvent(), wheelEvent() and scaleView(). Nothing special there...
A screenshot showing the application is attached. This might help you understand the situation.
I really don't know what happens... Please help me. :(
Regards,
Markus
EDIT: It might not be clear enough what I want: I want that the item under the mouse cursor moves. If it is the transmitter, then the transmitter should move. If it is a sensor then the sensor should move. If the rectangle is below the cursor then, the rectangle and it's children should move.
Re: QGraphicsView move item issues.
Use the following flags on your items:
QGraphicsItem::ItemIsMovable
QGraphicsItem::ItemIsSelectable (if needed)
QGraphicsItem::ItemSendsGeometryChanges
More flags:
http://doc.qt.nokia.com/4.6/qgraphic...sItemFlag-enum
QGraphicsView lets you move items out of the box, you don't need to add code for that. You only need to add code to handle the items in detail, like what to do when selecting an item or what happens if you move the item.
Re: QGraphicsView move item issues.
Thank you for the answer. Unfortunately it does not solve my problem. ItemIsMovable was already set to true.
Setting ItemIsSelectable and ItemSendsGeometryChanges to true does not change much: It is only shown that the item I can move (the same items I could move before) are now selected. I cannot "unselect" this item or select another one.
Re: QGraphicsView move item issues.
I found the reason for the behaviour: In UIGraphicsScene::mouseReleaseEvent I forgot to pass the mouseEvent on to QGraphicsScene::mouseReleaseEvent:
Code:
{
emit insertFinished();
}