QT系列教程(21) 自定义模型的拖动实现

自定义模型的拖动

便捷类的拖动实现很简单,今天我们介绍自己定义的ListModel模型如何实现拖动。在之前的ListModel项目基础上,我们先对View视图实现拖动操作.

cpp 复制代码
 //设置选择模式为单选
    listView.setSelectionMode(QAbstractItemView::ExtendedSelection);
    //设置可拖拽
    listView.setDragEnabled(true);
    //设置可拖放
    listView.setAcceptDrops(true);
    //设置显示拖放位置
    listView.setDropIndicatorShown(true);

对模型实现拖动

在ListModel添加声明

cpp 复制代码
  //编写拖动逻辑
    virtual QStringList mimeTypes() const;
    virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
    virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
                              int row, int column, const QModelIndex &parent);
    virtual Qt::DropActions supportedDropActions() const;

自定义一个类型,用来表示拖动导出的类型

cpp 复制代码
//拖放时导出的类型
QStringList StringListModel:: mimeTypes() const{
    QStringList types;
    //自定义类型
    types << "application/zack.list";
    return types;
}

将拖动的数据放入mimedata中

cpp 复制代码
QMimeData *StringListModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData * mimeData = new QMimeData();
    //字节数组
    QByteArray encodeData;
    QDataStream stream(&encodeData, QIODevice::WriteOnly);
    foreach(const QModelIndex& index, indexes){
        if(index.isValid()){
            QString text = data(index, Qt::DisplayRole).toString();
            stream << text;
        }
    }

    //将数据放入到QMimeData中
    mimeData->setData("application/zack.list", encodeData);
    return mimeData;

}

将拖放的数据从mimedata中导出

cpp 复制代码
bool StringListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
    //如果放入的动作是ignoreaction
    if(action == Qt::IgnoreAction){
        return true;
    }
    //如果数据的格式不是指定的格式,那么返回false
    if(!data->hasFormat("application/zack.list")){
        return false;
    }

    //因为这里是列表, 只用一列, 所以列大于0时返回false
    if(column > 0){
        return false;
    }

    //设置开始插入行
    int beginRow;
    if(row != -1){
        beginRow = row;
    }else if(parent.isValid()){
        beginRow = parent.row();
    }else {
        beginRow = rowCount(QModelIndex());
    }

    //将数据从QMimeData 中读取出来, 然后插入到模型中
    QByteArray encodeData = data->data("application/zack.list");
    //stream流
    QDataStream stream(&encodeData, QIODevice::ReadOnly);
    //统计插入的数据
    QStringList newItems;
    //统计插入的行数
    int rows = 0;
    while(!stream.atEnd()){
        QString text;
        stream >> text;
        newItems << text;
        ++ rows;
    }
    //插入指定行数
    insertRows(beginRow, rows, QModelIndex());
    //批量修改行数数据
    foreach(const QString& text, newItems){
        QModelIndex idx = index(beginRow, 0, QModelIndex());
        setData(idx,text);
        beginRow++;
    }

    return true;
}

为了能让我们的item拖动,需要重新实现flags变量,使其支持拖放

cpp 复制代码
Qt::ItemFlags  StringListModel::flags(const QModelIndex& index) const{
    //索引无效可以接受放入操作
    if(!index.isValid())
         return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
    //索引有效,可以接受拖拽和放入操作
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable
            | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}

然后我们设置支持的拖放动作为移动和复制

cpp 复制代码
Qt::DropActions StringListModel::supportedDropActions() const
{
    //设置支持放入动作,允许copy和move
    return Qt::CopyAction | Qt::MoveAction;
}

拖动效果

源码链接

源码链接
https://gitee.com/secondtonone1/qt-learning-notes

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript