如何将特定的 QPixmap 拖放到 QGraphicsView 中?

How to drag and drop a specific QPixmap into a QGraphicsView?

在一个子类中 QListWidget 我有几个项目。下面显示的每个 QListWidget 项(例如“ROS Init”、“Images”等)都与特定图标相关联。

我遇到的问题是我试图拖放与该 QListWidget 项目对应的特定图标,但没有任何反应。

下面负责拖动的函数:

void ListView::startDrag(Qt::DropActions supportedActions)
{
    QMap<int, QString> icons;
    icons.insert(IT_RosInit, "ROS Init");
    icons.insert(IT_Images, "Images");
    icons.insert(IT_Path, "Path");
    icons.insert(IT_RosShutDown, "ROS Shutdown");

    if (supportedActions & Qt::CopyAction)
    {
        const QList<QListWidgetItem *> &m_items(selectedItems());
        if (m_items.isEmpty())
            return;

        QPixmap pixmapLaser("/home/images/laserscan.png");
        QPixmap pixmapPCloud2("/home/images/pcloud2.png");
        // etc ...

        QStringList iconImages;

        for(int i = 0; i < icons.count(); ++i)
        {
            for (const QString &tableType : iconImages) {
                if (tableType == "ROS Init")
                {
                    auto *data = mimeData(m_items);
                    auto *drag = new QDrag(this);
                    drag->setPixmap(pixmapLaser);
                    drag->setMimeData(data);
                    drag->setHotSpot(pixmapLaser.rect().center());
                    drag->exec(Qt::CopyAction);
                 }
                else if(tableType == "Images")
                {
                    auto *data2 = mimeData(m_items);
                    auto *drag2 = new QDrag(this);
                    drag2->setPixmap(pixmapPCloud2);
                    drag2->setMimeData(data2);
                    drag2->setHotSpot(pixmapPCloud2.rect().center());
                    drag2->exec(Qt::CopyAction);
                }
            }
        }
    }
    else
    {
        QListWidget::startDrag(supportedActions);
    }
}

子类化 QListWidget 之后,我刚刚重新实现了常用的拖放功能。所有其他功能都正常工作,但 startDrag 事实上,当我尝试拖动正确的 QPixmap 时,我实际上没有看到任何东西被拖动。

我咨询了 this source, useful, and also ,这很有用,但它没有重新实现 startDrag,而是 dropEvent,这对我来说不是问题,因为它运行良好。

我也咨询了this source and ,但这也无助于解决问题。

感谢您阐明此事以解决问题

解决方案

我会通过以下方式解决这个问题:

  1. 设置 QListWidgetItem ItemIsDragEnabled 标志以启用项目拖动:

     item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
    
  2. 为每个项目设置所需的数据:

     item->setData(Qt::UserRole, type);
    

其中 type 是枚举值之一 IT_RosInitIT_Images

  1. 启用 ListWidget 的拖动功能:

     setDragEnabled(true);
     setDragDropMode(QAbstractItemView::DragOnly);
    
  2. 使用项目设置来设置 QDrag 对象,在 startDrag.

    中创建

例子

这是我为您准备的示例,用于演示如何实施建议的解决方案:

MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    auto *l = new QVBoxLayout(this);
    auto *list = new ListView(this);

    list->addItem(createItem(":/pix/images/laserscan.png", tr("RosInit"), IT_RosInit));
    list->addItem(createItem(":/pix/images/icons/pcloud2.png", tr("Images"), IT_Images));
    list->addItem(createItem(":/pix/images/icons/some_icon.png", tr("Path"), IT_Path));
    list->addItem(createItem(":/pix/images/icons/another_icon.png", tr("RosShutDown"), IT_RosShutDown));

    l->addWidget(list);

    resize(300, 400);
    setWindowTitle("IconDrag");
}

QListWidgetItem *MainWindow::createItem(const QString &pm, const QString &text, int type)
{
    auto *item = new QListWidgetItem(QIcon(QPixmap(pm)), text);

    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
    item->setData(Qt::UserRole, type);

    return item;
}

ListView.cpp

ListView::ListView(QWidget *parent) :
    QListWidget(parent)
{
    setDragEnabled(true);
    setDragDropMode(QAbstractItemView::DragOnly);
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setSelectionMode(QAbstractItemView::SingleSelection);
}

void ListView::startDrag(Qt::DropActions supportedActions)
{
    if (supportedActions & Qt::CopyAction) {
        const QList<QListWidgetItem *> &items(selectedItems());

        if (items.isEmpty())
            return;

        const QPixmap &pm(items.first()->icon().pixmap(64));
        auto *item = items.first();
        auto *mimeData = new QMimeData();
        auto *drag = new QDrag(this);

        mimeData->setData("text/plain", item->data(Qt::UserRole).toByteArray());

        drag->setPixmap(pm);
        drag->setMimeData(mimeData);
        drag->setHotSpot(pm.rect().center());
        drag->exec(Qt::CopyAction);
    }
}