可拖拽图标示例

可拖拽图标示例展示了如何在同一应用程序中的小部件之间以及不同应用程序之间拖放图像数据。

在许多使用拖放操作的情况中,用户从特定的控件中开始拖动,并将数据放置到另一个控件上。在这个示例中,我们通过子类化 QLabel 创建用于拖放的标签,并将它们放置在 QWidget 中,这个 QWidget 既充当容器也充当拖放目标。

此外,当进行拖放操作时,我们不仅想要发送图像。我们还想发送有关用户在图像中单击位置的信息,以便用户可以将其精确地放置在拖放目标上。这种详细程度意味着我们必须为我们数据创建一个自定义 MIME 类型。

DragWidget 类定义

我们用来显示图标的图标控件是从 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;
};

由于 QLabel 类提供了我们所需的图标的大部分功能,我们只需要重新实现 QWidget::mousePressEvent() 来提供拖放功能。

DragWidget 类实现

DragWidget 构造函数在控件上设置了一个属性,以确保它在关闭时被删除

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);
}

为了从图标中启用拖动,我们需要对鼠标按下事件进行操作。我们通过重新实现 QWidget::mousePressEvent() 并设置一个 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());

由于我们将发送图标图像数据和关于用户在图标控件中点击的信息,我们构建一个 QByteArray 并使用 QDataStream 打包细节。

为了互操作性,拖放操作使用 MIME 类型描述它们包含的数据。在 Qt 中,我们使用 QMimeData 对象来描述此数据

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

我们为此选择一个非官方 MIME 类型,并将 QByteArray 传递给 MIME 数据对象。

拖放操作本身由一个 QDrag 对象处理

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

在这里,我们将数据传递给拖放对象,设置一个在操作过程中与光标一起显示的位图,并定义一个热点位置,该位置将此位图的位置置于光标下方。

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。本文件中包含的文档贡献属于各自的版权所有者。所提供的文档根据自由软件基金会的版本1.3GNU自由文档许可协议授权。Qt及其标志是Qt公司在芬兰及其他国家/地区的商标。商标。所有其他商标均属于其各自的拥有者。