7

I have to make something like the iOS interface, 3x3 field of icons that can be dragged to change their position, and then remember it in an XML file.

I decided to use Grid class (QWidget is parent) as a container and my own class, inherited from QWidget, as elements.

Now I'm trying to learn how to perform a drag & drop for QWidget, but it seems like you are only able to drop onto a QWidget, but it's impossible to drag it.

Is it impossible? How do I move this thing?

TZHX
  • 5,291
  • 15
  • 47
  • 56
Leonid Bor
  • 2,064
  • 6
  • 27
  • 47
  • Do you just want to move it, or to drag/drop it? Just moving it is easier (http://stackoverflow.com/questions/12219727/dragging-moving-a-qpushbutton-in-pyqt), drag/drop gets complicated (http://stackoverflow.com/questions/24582383/qmimedata-setting-and-getting-the-right-mime-types-for-arbitrary-widgets). – eric Jul 09 '14 at 14:51

3 Answers3

6

Dragging a widget isn't that easy. Plenty of coding you have to do yourself.

From the Qt Docs:

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton
        && iconLabel->geometry().contains(event->pos())) {

        QDrag *drag = new QDrag(this);
        QMimeData *mimeData = new QMimeData;

        mimeData->setText(commentEdit->toPlainText());
        drag->setMimeData(mimeData);
        drag->setPixmap(iconPixmap);

        Qt::DropAction dropAction = drag->exec();
        ...
    }
}

This means, when your widget receives a message that it is to be dragged, e.g. like with a mousepress, it has to create a QDrag object.

In the QDrag object you can set a pixmap, which represents your dragged widget. If you hide your widget at this point, it looks like as if your mouse pointer 'took' the widget.

Additionally you need a QMimeData object. In this you can put all kinds of data, which describes your widget. In your use case something which allows you to identify your widget. Because, and here comes the difficult part: You have to do the moving yourself.

The widget, which is the grid's parent, receives the drop event and reads from the mime data, which widget wishes to me moved. From the QDropEvent it gets the point where the widget is to be moved. That's what you have to code: The actual repositioning in your grid layout. And don't forget to update the xml.

eric
  • 7,142
  • 12
  • 72
  • 138
Greenflow
  • 3,935
  • 2
  • 17
  • 28
  • and what about I just remember which element was moving, read on which other element it was dropped, then remember the second one, replace it with first and put second on the place of first with addWidget() and removeWidget()? – Leonid Bor Aug 18 '13 at 14:55
  • @Leonid Bor, the QDrag object gives you a way to have an icon under your mouse pointer. And it gives to a way to pass data about the dragged object to the drop receiver. If you can get this information otherwise... no problem. addWidget() and removeWidget() are certainly one way to actually perform the move. – Greenflow Aug 18 '13 at 15:03
4

do a trick then you can able to drag QWidget also,

QPixmap *widgetPixmap = new QPixmap;
yourWidget->render(widgetPixmap); // rendering the current widget to t_iconTPixmap

Now use this widgetPixmap as the pixmap for yourDragObject->setPixmap();

example,

void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton
    && iconLabel->geometry().contains(event->pos())) {

    QDrag *drag = new QDrag(this);
    QMimeData *mimeData = new QMimeData;

    mimeData->setText(commentEdit->toPlainText()); 

    QPixmap *widgetPixmap = new QPixmap;
    yourWidget->render(widgetPixmap);

    drag->setMimeData(mimeData);
    drag->setPixmap(widgetPixmap);

    Qt::DropAction dropAction = drag->exec();
    ...
   }
}
Akhil V Suku
  • 870
  • 2
  • 13
  • 34
0

The Qt wiki contains a QtQuick example on how to emulate the iOS icon interface with less then 80 lines of code.

You can find it here.

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • I think, if you read the qml, you can translate it into a QGridLayout/QWidget layout. After all, qml is just an other language describing the layout. – huysentruitw Aug 18 '13 at 15:00