【问题标题】:Qt - How to show image/icon/data while dragging an item?Qt - 如何在拖动项目时显示图像/图标/数据?
【发布时间】:2018-05-10 18:40:41
【问题描述】:

我有一个应用程序,我可以将一个项目拖到 QGraphicsScene 并根据项目文本创建一个新对象,但是如何在项目周围移动时更改正在显示的数据?

例如,我想显示一个图标而不是文本:

我有一个包含一些项目的列表:

OptionList::OptionList(QWidget *parent) : QListWidget(parent)
{
    this->setDragEnabled(true);
    this->setDropIndicatorShown(true);
    this->setSelectionMode(QAbstractItemView::SingleSelection);
    this->setDefaultDropAction(Qt::CopyAction);
    this->setViewMode(QListView::ListMode);

    for(const QString &color : {"Blue", "Red", "Green", "Yellow"})
    {
        OptionItem *item = new OptionItem;
        item->setText(color);
        item->setFlags(Qt::ItemIsEnabled| Qt::ItemIsSelectable| Qt::ItemIsDragEnabled);
        addItem(item);
    }
}

我将元素放入场景中以创建一个新对象:

MyScene::MyScene()
{
    setBackgroundBrush(Qt::lightGray);
}

void MyScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    event->setAccepted(true);
}

void MyScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    event->setAccepted(true);
}

void MyScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    QByteArray encoded = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);

    QStringList colors;

    while (!stream.atEnd())
    {
        int row, col;
        QMap<int,  QVariant> roleDataMap;
        stream >> row >> col >> roleDataMap;
        colors << roleDataMap[Qt::DisplayRole].toString();
    }

    QPointF posView = event->scenePos() ;

    for(const QString & color: colors)
    {
        Block *newBlock = new Block(color);
        newBlock->setPos(posView);
        addItem(newBlock);
    }
}

然后,我创建了派生自 QListWidgetItem 的 OptionItem 类,并重新实现了 mousePressEvent、mouseMoveEvent 和 mouseReleaseEvent

OptionItem::OptionItem()
{

}

void OptionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    event->setAccepted(true);
}

void OptionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QDrag *drag = new QDrag(event->widget());

    QMimeData *mime = new QMimeData;

    QImage image(":/images/MyIcon_icon.png");
    mime->setImageData(image);

    drag->setMimeData(mime);
    drag->setPixmap(QPixmap::fromImage(image));
    drag->setHotSpot(QPoint(15, 30));

    drag->exec();

    event->setAccepted(true);
}

void OptionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    event->setAccepted(true);
}

我尝试按照 Qt Creator 中的拖放机器人示例进行操作,但这不是一回事

当我开始拖动项目时,图像似乎出现得很快

有没有办法在整个操作中拖动项目时显示图标?

【问题讨论】:

    标签: c++ qt qt5


    【解决方案1】:

    QAbstractItemView 继承的类支持默认拖动,因此它们已经实现了方法,而不是您指出的示例显示了如何为某些没有它的类实现此功能,您的任务很简单,你必须覆盖QListWidget的方法startDrag

    optionilist.h

    #ifndef OPTIONLIST_H
    #define OPTIONLIST_H
    
    #include <QListWidget>
    
    
    class OptionList: public QListWidget{
    public:
        OptionList(QWidget* parent=nullptr);
    
    protected:
        void startDrag(Qt::DropActions supportedActions);
    };
    
    #endif // OPTIONLIST_H
    

    optionlist.cpp

    #include "optionlist.h"
    
    #include <QDrag>
    
    OptionList::OptionList(QWidget *parent): QListWidget(parent){
    
        setDragEnabled(true);
        setDropIndicatorShown(true);
        setSelectionMode(QAbstractItemView::SingleSelection);
        setDefaultDropAction(Qt::CopyAction);
        setViewMode(QListView::ListMode);
    
        for(const QString &color : {"Blue", "Red", "Green", "Yellow"}){
            QListWidgetItem *blue = new QListWidgetItem;
            blue->setText(color);
            blue->setFlags(Qt::ItemIsEnabled| Qt::ItemIsSelectable| Qt::ItemIsDragEnabled);
            addItem(blue);
        }
    }
    
    void OptionList::startDrag(Qt::DropActions supportedActions){
        if(supportedActions & Qt::CopyAction){
            QList<QListWidgetItem *> m_items = selectedItems();
            if(m_items.isEmpty())
                return;
            QMimeData *data = mimeData(m_items);
            QDrag *drag = new QDrag(this);
            QPixmap pixmap(":/images/MyIcon_icon.png");
            drag->setPixmap(pixmap);
            drag->setMimeData(data);
            drag->setHotSpot(pixmap.rect().center());
            drag->exec(Qt::CopyAction);
        }
        else
            QListWidget::startDrag(supportedActions);
    
    }
    

    完整代码可以在以下link找到。

    【讨论】:

    • 我在QListWidget中使用了startDrag方法,当我开始拖动item时,应用程序输出打印如下错误:QDrag: No mimedata set before start the drag
    • 我使用了调试器,看起来变量数据到达拖动时没有值->setMimeData(data);也许问题出在 mimeData() 函数上?应用程序成功运行,但当我尝试拖动项目时,应用程序输出中出现消息“QDrag:在开始拖动之前未设置 mimedata”。我也尝试编译您的代码,但由于 nullptr 标识符,我不得不在 .pro 文件中设置 CONFIG += c++11,同样的消息仍然出现在应用程序输出中。
    • 我尝试了你的项目并得到了同样的信息。我已经消除了 OptionItem 实现。我正在使用 Qt 5.4.1 版本。这是我的代码的链接:github.com/Gabriel-22/myqt/tree/master/Project1
    【解决方案2】:

    以上是正确的!

    还要注意drag-&gt;setMimeData(data);需要在drag-&gt;setPixmap(pixmap);之后调用。

    否则,在拖拽移动的过程中,它会显示原来的mimedata类型,而不是显示图像/图标。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 2020-07-17
      • 2016-03-11
      • 1970-01-01
      相关资源
      最近更新 更多