模型视图 上控件的拖拽

设置支持拖拽

视图类的设置

  1. 视图允许拖拽setDragEnabled(true)

  1. 视图接收拖拽setAcceptDrops(true);

  1. 视图控制插入拖拽的位置setDropIndicatorShown(true);属性用于控制在拖拽过程中显示当前拖拽到的位置,当释放时则在当前拖拽位置覆盖或插入

模型对拖放操作的支持

模型对拖放的支持通过重写QAbstractItemModel::supportedDropActions() 虚函数来指定。

virtual Qt::DropActions supportedDropActions() const;
Qt::DropActions DragDropListModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

启用项目的拖放

模型通过重新实现 QAbstractItemModel::flags() 函数以提供合适的标志,向视图指示哪些项目可以拖动,哪些将接受放置。例如,为行号小于5的项设置Qt::ItemIsDragEnabled 和 Qt::ItemIsDropEnabled 值,即行号小于5的项可拖放:

Qt::ItemFlags DragDropListModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);
 
    if (index.row() < 5)
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
    else
        return Qt::ItemIsEnabled;
}

拖放的MIME数据

在拖放操作中从模型导出数据项时,它们被编码为与一种或多种 MIME 类型相对应的适当格式。

模型通过重新实现 QAbstractItemModel::mimeTypes() 函数并返回标准 MIME 类型列表来声明它们可用于提供项目的 MIME 类型。

例如,仅提供纯文本的模型将提供以下实现:

QStringList DragDropListModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list";
    return types;
}

QAbstractItemModel::mimeData() 函数提供 QMimeData 对象的具体内容。

QMimeData *DragDropListModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *mimeData = new QMimeData;
    QByteArray encodedData;
 
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
 
    for (const QModelIndex &index : indexes) {
        if (index.isValid()) {
            QString text = data(index, Qt::DisplayRole).toString();
            stream << text;
        }
    }
 
    mimeData->setData("application/vnd.text.list", encodedData);
    return mimeData;
}

将拖入的数据插入模型

拖入的数据由模型重新实现的 QAbstractItemModel::dropMimeData() 处理。前提是要对视图设置视图接收拖拽setAcceptDrops(true)


bool DragDropListModel::dropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    if (!canDropMimeData(data, action, row, column, parent))
        return false;
 
    if (action == Qt::IgnoreAction)
        return true;
 
    int beginRow;
 
    if (row != -1)
        beginRow = row;
    else if (parent.isValid())
        beginRow = parent.row();
    else
        beginRow = rowCount(QModelIndex());
 
    QByteArray encodedData = data->data("application/vnd.text.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;
 
    while (!stream.atEnd()) {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }
 
    insertRows(beginRow, rows, QModelIndex());
    for (const QString &text : qAsConst(newItems)) {
        QModelIndex idx = index(beginRow, 0, QModelIndex());
        setData(idx, text + "__拖入数据");
        beginRow++;
    }
 
    return true;
}

另外:

模型可以通过重新实现 QAbstractItemModel::canDropMimeData() 来禁止删除某些项目。

bool DragDropListModel::canDropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(action);
    Q_UNUSED(row);
    Q_UNUSED(parent);
 
    if (!data->hasFormat("application/vnd.text.list"))
        return false;
 
    if (column > 0)
        return false;
 
    return true;
}

#include <QStandardItemModel>
 
class DragDropListModel : public QStandardItemModel
{
public:
    explicit DragDropListModel(QObject *parent = nullptr);
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    QStringList mimeTypes() const override;
    QMimeData *mimeData(const QModelIndexList &indexes) const override;
    bool canDropMimeData(const QMimeData *data, Qt::DropAction action,
                         int row, int column, const QModelIndex &parent) const override;
    bool dropMimeData(const QMimeData *data, Qt::DropAction action,
                      int row, int column, const QModelIndex &parent)override;
};
 
DragDropListModel::DragDropListModel(QObject *parent) : QStandardItemModel(parent)
{
}
 
Qt::ItemFlags DragDropListModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);
    return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
}
 
QStringList DragDropListModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list";
 
    return types;
}
 
QMimeData *DragDropListModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *mimeData = new QMimeData;
    QByteArray encodedData;
 
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
 
    for (const QModelIndex &index : indexes)
    {
        if (index.isValid())
        {
            QString text = data(index, Qt::DisplayRole).toString();
            stream << text;
        }
    }
 
    mimeData->setData("application/vnd.text.list", encodedData);
    return mimeData;
}
 
bool DragDropListModel::canDropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(action);
    Q_UNUSED(row);
    Q_UNUSED(parent);
 
    if (!data->hasFormat("application/vnd.text.list"))
        return false;
 
    if (column > 0)
        return false;
 
    return true;
}
 
bool DragDropListModel::dropMimeData(const QMimeData *data,
    Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    if (!canDropMimeData(data, action, row, column, parent))
        return false;
 
    if (action == Qt::IgnoreAction)
        return true;
 
    int beginRow;
 
    if (row != -1)
        beginRow = row;
    else if (parent.isValid())
        beginRow = parent.row();
    else
        beginRow = rowCount(QModelIndex());
 
    QByteArray encodedData = data->data("application/vnd.text.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;
 
    while (!stream.atEnd()) {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }
 
    insertRows(beginRow, rows, QModelIndex());
    for (const QString &text : qAsConst(newItems)) {
        QModelIndex idx = index(beginRow, 0, QModelIndex());
        setData(idx, text + "__拖入数据");
        beginRow++;
    }
 
    return true;
}

    QListView listView;
    listView.setSelectionMode(QAbstractItemView::ExtendedSelection);
    listView.setDragEnabled(true);
    listView.setAcceptDrops(true);
    listView.setDropIndicatorShown(true);
 
    DragDropListModel * model = new DragDropListModel;
    model->setColumnCount(1);
    model->setRowCount(10);
 
    for(int i = 0;i < 10;++i)
        model->setData(model->index(i,0),QString("data_%1").arg(i));
 
    listView.setModel(model);
    listView.show();

版权声明:本文为CSDN博主「友善啊,朋友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/kenfan1647/article/details/119177119

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值