拖动图标示例显示了如何在同一应用程序中的小部件之间以及不同应用程序之间拖放图像数据。
在使用拖放的许多情况下,用户开始从特定的窗口小部件拖放,并将有效负载拖放到另一个窗口小部件上。在此示例中,我们将QLabel子类化以创建用作拖动源的标签,并将其放置在同时充当容器和放置站点的QWidget中。
另外,当发生拖放操作时,我们希望发送的不仅仅是图像。我们还希望发送有关用户在图像中单击位置的信息,以便用户可以将其精确放置在放置目标上。这种详细程度意味着我们必须为数据创建自定义MIME类型。
DragWidget类定义
用于显示图标的图标小部件是QLabel的子类:
代码语言:javascript复制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构造函数在小部件上设置一个属性,以确保被关闭时将其删除:
代码语言:javascript复制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->pos()));
if (!child)
return;
QPixmap pixmap = child->pixmap(Qt::ReturnByValue);
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << QPoint(event->pos() - child->pos());
由于我们将发送图标的像素图数据以及图标小部件中有关用户单击的信息,因此我们构造了一个QByteArray并使用QDataStream打包了详细信息。
为了实现互操作性,拖放操作使用MIME类型描述它们包含的数据。在Qt中,我们使用QMimeData对象描述此数据:
代码语言:javascript复制 QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-dnditemdata", itemData);
为此,我们选择一种非官方的MIME类型,并将QByteArray提供给MIME数据对象。
拖放操作本身由QDrag对象处理:
代码语言:javascript复制 QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos() - child->pos());
在这里,我们将数据传递到拖动对象,设置在操作期间将在光标旁边显示的像素图,并定义将像素图的位置置于光标下方的热点位置。
关于更多
- 在QtCreator软件可以找到:
- 或在以下Qt安装目录找到:
C:Qt{你的Qt版本}Examples{你的Qt版本}widgetsdraganddropdraggableicons
- 相关链接
https://doc.qt.io/qt-5/qtwidgets-draganddrop-draggableicons-example.html