Confused regarding positions and reference frames in drag-and-drop scenario
-
I haven't got a huge amount of experience in Qt or in C++, but I've been playing around with the "Drag and drop icons" tutorial, reading documentation and trying to learn as much as possible.
Now, I'm in this situation where I'm trying to drag items from a QTreeWidget into a frame. I want to drag an up-scaled version of the icon for the particular list element. My (admittedly not very pretty) solution is to create a pointer to the QTreeWidgetItem, check the text value on this, and set the dragged pixmap accordingly. It's not code that I'm particularly proud of, but it seems to work...
My main headache is the position syntax. When I start to drag an item, the pixmap is displayed in a different location depending on which element I'm dragging. If I drag the topmost item in my QTreeWidget, the top left corner of the pixmap is rendered exactly where my pointer is. However, if I drag any of the lower items, the pixmap is rendered about one pixel to the left and something like 15 pixels above the pointer. Presumably, there is something I don't understand about the child->pos() property? The documentation states that it "holds the position of the widget within its parent widget", but the parent widget of the QDrag should be my QTreeWidget object, right? And this object is presumably also the parent of the event as well as the "child" pointer? In that case, when I create "child" as a static_cast of "childAt(event->pos())" then to me it seems that rendering the pixmap at child->pos() should result in a pixmap exactly where the pointer is. I'm obviously confused regarding the parenthood of events and the created pointers. Could anyone clear this up for me in an understandable manner?
Sorry about the long post. I'll attach the code for the constructor of my ReactorList class as well as the mousePressEvent function.
@ReactorList::ReactorList(QWidget *parent) :
QTreeWidget(parent)
{
setAcceptDrops(false);
// These should be replaced by an AddModule function
QTreeWidgetItem *HouseIcon = new QTreeWidgetItem(this);
HouseIcon->setText(0,tr("House"));
HouseIcon->setIcon(0,QIcon(QPixmap(":/images/house.png")));
QTreeWidgetItem *BoatIcon = new QTreeWidgetItem(this);
BoatIcon->setText(0,tr("Boat"));
BoatIcon->setIcon(0,QIcon(QPixmap(":/images/boat.png")));
QTreeWidgetItem *CarIcon = new QTreeWidgetItem(this);
CarIcon->setText(0,tr("Car"));
CarIcon->setIcon(0,QIcon(QPixmap(":/images/car.png")));
}@@void ReactorList::mousePressEvent(QMouseEvent *event)
{QLabel *child = static_cast<QLabel*>(childAt(event->pos())); // This pointer is created so that we can check the text value of the clicked QTreeWidgetItem QTreeWidgetItem *child2 = itemAt(event->pos()); if (!child) return; child->setAttribute(Qt::WA_DeleteOnClose); child->setScaledContents(true); QPixmap pixmap; if(child2->text(0) == "House") { pixmap = QPixmap(":/images/house1.png"); } else if(child2->text(0) == "Boat") { pixmap = QPixmap(":/images/boat1.png"); } else if(child2->text(0) == "Car") { pixmap = QPixmap(":/images/car1.png"); } else { // this is only here for redundancy pixmap = QPixmap(":/images/car1.png"); } QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << pixmap << QPoint(child->pos()); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-dnditemdata", itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(child->pos()); if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) child->close(); else { child->show(); if(child->property("ContainsText") == 0) { child->setPixmap(pixmap); } }
}@