Sur cette page

Exemple d'icônes glissantes

L'exemple des icônes glissantes montre comment faire glisser et déposer des données d'image entre les widgets d'une même application et entre différentes applications.

Application avec des icônes qui réagissent aux événements de glisser-déposer

Dans de nombreuses situations où le glisser-déposer est utilisé, l'utilisateur commence à glisser à partir d'un widget particulier et dépose la charge utile sur un autre widget. Dans cet exemple, nous sous-classons QLabel pour créer des étiquettes que nous utilisons comme sources de glisser-déposer, et nous les plaçons à l'intérieur de QWidgets qui servent à la fois de conteneurs et de sites de dépôt.

En outre, lorsqu'une opération de glisser-déposer se produit, nous voulons envoyer plus qu'une simple image. Nous voulons également envoyer des informations sur l'endroit où l'utilisateur a cliqué dans l'image afin qu'il puisse la placer précisément sur la cible de dépôt. Ce niveau de détail signifie que nous devons créer un type MIME personnalisé pour nos données.

Définition de la classe DragWidget

Les widgets d'icônes que nous utilisons pour afficher les icônes sont des sous-classes de la classe QLabel:

class DragWidget : public QFrame
{
public:
    explicit DragWidget(QWidget *parent = nullptr);

protected:
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dragMoveEvent(QDragMoveEvent *event) override;
    void dropEvent(QDropEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
};

Étant donné que la classe QLabel fournit la plupart des éléments dont nous avons besoin pour l'icône, il nous suffit de réimplémenter la classe QWidget::mousePressEvent() pour fournir des fonctions de glisser-déposer.

Mise en œuvre de la classe DragWidget

Le constructeur de DragWidget définit un attribut sur le widget qui garantit qu'il sera supprimé lorsqu'il sera fermé :

DragWidget::DragWidget(QWidget *parent)
    : QFrame(parent)
{
    setMinimumSize(200, 200);
    setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
    setAcceptDrops(true);

    QLabel *boatIcon = new QLabel(this);
    boatIcon->setPixmap(QPixmap(":/images/boat.png"));
    boatIcon->move(10, 10);
    boatIcon->show();
    boatIcon->setAttribute(Qt::WA_DeleteOnClose);

    QLabel *carIcon = new QLabel(this);
    carIcon->setPixmap(QPixmap(":/images/car.png"));
    carIcon->move(100, 10);
    carIcon->show();
    carIcon->setAttribute(Qt::WA_DeleteOnClose);

    QLabel *houseIcon = new QLabel(this);
    houseIcon->setPixmap(QPixmap(":/images/house.png"));
    houseIcon->move(10, 80);
    houseIcon->show();
    houseIcon->setAttribute(Qt::WA_DeleteOnClose);
}

Pour permettre le glissement à partir de l'icône, nous devons agir sur un événement de pression de la souris. Pour ce faire, nous réimplémentons QWidget::mousePressEvent() et créons un objet QDrag.

void DragWidget::mousePressEvent(QMouseEvent *event)
{
    QLabel *child = static_cast<QLabel*>(childAt(event->position().toPoint()));
    if (!child)
        return;

    QPixmap pixmap = child->pixmap();

    QByteArray itemData;
    QDataStream dataStream(&itemData, QIODevice::WriteOnly);
    dataStream << pixmap << QPoint(event->position().toPoint() - child->pos());

Étant donné que nous enverrons des données pixmap pour l'icône et des informations sur le clic de l'utilisateur dans le widget de l'icône, nous construisons un QByteArray et regroupons les détails à l'aide d'un QDataStream.

Pour des raisons d'interopérabilité, les opérations de glisser-déposer décrivent les données qu'elles contiennent à l'aide de types MIME. Dans Qt XML, nous décrivons ces données à l'aide d'un objet QMimeData:

    QMimeData *mimeData = new QMimeData;
    mimeData->setData("application/x-dnditemdata", itemData);

Nous choisissons un type MIME non officiel à cette fin et fournissons l'adresse QByteArray à l'objet de données MIME.

L'opération de glisser-déposer elle-même est gérée par un objet QDrag:

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setPixmap(pixmap);
    drag->setHotSpot(event->position().toPoint() - child->pos());

Ici, nous transmettons les données à l'objet drag, nous définissons une pixmap qui sera affichée à côté du curseur pendant l'opération et nous définissons la position d'un hot spot qui place la position de cette pixmap sous le curseur.

Exemple de projet @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.