views:

67

answers:

2

Suppose I want my draggable widget to move differently than just staying under my cursor while being dragged. For instance, having the widget move only in one axis, or have the widget move double the distance between the cursor and the drag starting point. Which method should I override to define this kind of behaviour?

A: 

For a widget these four methods control the behaviour of a dragged widget :

virtual void dragEnterEvent ( QDragEnterEvent * event )
virtual void dragLeaveEvent ( QDragLeaveEvent * event )
virtual void dragMoveEvent ( QDragMoveEvent * event )
virtual void dropEvent ( QDropEvent * event )

I guess you have to reimplement the dragMoveEvent to achieve what you want.

gregseth
Are there any examples of what I have to do inside dragMoveEvent() to control the widget's behaviour? I tried to mess with the drag-and-drop robot example, by changing QDrag's hotspot attribute in the draggable widget's mouseMoveEvent(), but it gets called only at the beginning of the drag, so it's not good enough.
David McDavidson
+1  A: 

I think you should ask yourself a question: do you have some draggable elements I want to drag to specific targets (for example you have widgets that represent pieces of different shapes that should be dragged on other widgets representing holes and each "hole" accepts only pieces of the same shape) or do you just want to move one widget over the other widget?

If you need drag & drop functionality, it seems to me that you can't really change the behavior during mouse moving - it's more or less hardcoded into QDrag object.

If you just want to move stuff around, you should be able to do it only be reimplementing mouse Move/Press/Release events (you might also need to enable mouse tracking by QWidget::setMouseTracking method).

EDIT:

This is sample code for draggable label for "just moving stuff around":

#ifndef DRAGGABLELABEL_H
#define DRAGGABLELABEL_H

#include <QLabel>
#include <QPoint>
#include <QMouseEvent>

class DraggableLabel : public QLabel
{
Q_OBJECT

public:
    explicit DraggableLabel(const QString &text, QWidget *parent = 0) : QLabel(text, parent) {}

protected:
    void mousePressEvent(QMouseEvent *event) {
        dragStart = event->pos();
    }

    void mouseMoveEvent(QMouseEvent *event) {
        setGeometry(QRect(geometry().topLeft() + event->pos() - dragStart, rect().size()));
    }

private:
    QPoint dragStart;

};

#endif // DRAGGABLELABEL_H

Now you just need to add it to your main widget:

#include <QApplication>
#include <QWidget>

#include "draggablelabel.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget mainWindow;

    DraggableLabel *label = new DraggableLabel("Test", &mainWindow);

    mainWindow.setMinimumSize(200, 200);
    mainWindow.show();

    return a.exec();
}

You can experiment with moveMouseEvent to achieve dragging only in one axis.

chalup
I thought that moving stuff around was drag-and-drop. Well, is it possible to have the widget move only in one axis then? If I have several columns of draggable widgets, and when dragging one of them I'd like to have its movement restricted to its own column. Can it be done?
David McDavidson
Fantastic, thanks!
David McDavidson