我正在尝试从一个QListView到另一个QListView实现拖放项目(普通/文本)。拖动开始很好(我甚至能够将项目拖放到另一个接受文本丢弃的应用程序),但我的第二个QListView由于某种原因不接受丢弃。 以下是配置列表视图的方式:
ui->lessonsListView->setAcceptDrops(true);
ui->lessonsListView->setDropIndicatorShown(true);
ui->lessonsListView->setDragDropMode(QAbstractItemView::DropOnly);
ui->lessonsListView->setDragDropOverwriteMode(true);
此listView的代理模型实现了下一个方法:
Qt::ItemFlags LessonsProxyModel::flags(const QModelIndex &index) const
{
qDebug() << __FUNCTION__;
return Qt::ItemIsDropEnabled | QSortFilterProxyModel::flags(index);
}
Qt::DropActions LessonsProxyModel::supportedDropActions() const
{
qDebug() << __FUNCTION__;
return Qt::MoveAction;
}
bool LessonsProxyModel::canDropMimeData(const QMimeData *data,
Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
qDebug() << __FUNCTION__;
Q_UNUSED(action);
Q_UNUSED(row);
Q_UNUSED(column);
if (!data->hasFormat("text/plain") || !parent.isValid())
return false;
return true;
}
bool LessonsProxyModel::dropMimeData(const QMimeData *data,
Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
qDebug() << __FUNCTION__;
if (!canDropMimeData(data, action, row, column, parent))
return false;
emit dataDropped(data, parent);
return true;
}
从应用程序输出中,我看到只调用了supportedDropActions()
和flags()
。 canDropMimeData()
和dropMimeData()
都没有打过电话。我究竟做错了什么?
任何提示将不胜感激。
谢谢!
编辑:
以防万一:下面是listView的源代码,并且启动了这些拖动的模型: listView设置:
ui->abonsListView->setDragEnabled(true);
proxyModel代码:
Qt::ItemFlags AbonsProxyModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsDragEnabled | QSortFilterProxyModel::flags(index);
}
Qt::DropActions AbonsProxyModel::supportedDragActions() const
{
qDebug() << __FUNCTION__;
return Qt::MoveAction;
}
QStringList AbonsProxyModel::mimeTypes() const
{
qDebug() << __FUNCTION__;
QStringList types;
types << "text/plain";
return types;
}
QMimeData *AbonsProxyModel::mimeData(const QModelIndexList &indexes) const
{
qDebug() << __FUNCTION__;
QMimeData *mimeData = new QMimeData();
foreach (const QModelIndex &index, indexes)
if (index.isValid())
{
mimeData->setText(data(index, AbonsModel::Id).toString());
qDebug() << __FUNCTION__;
return mimeData;
}
return mimeData;
}
答案 0 :(得分:2)
我终于找到了答案!当我开始编写此代码时,我从Qt docs Using Drag and Drop with Item Views中复制了一些内容,在本文中,他们只是错过了const
说明符来重新实现canDropMimeData()
。因此我的canDropMimeData()
版本变为非虚拟版本,QListView只调用基类QAbstractProxyModel
中的方法。我添加了const
- 所有内容都像没有任何子类的魅力一样。
答案 1 :(得分:0)
我对代理模型的经验不多。通过文档,我想我已经大致了解这两个函数是什么。这些函数不会自动调用。你必须打电话给#34;它们来自你的观点。
首先,检查您是否拥有正确的数据是模型的工作。因此,这些是模型中的两个便利功能,可以简化您的工作。这些是特定于模型的函数,而不是泛型函数,因此永远不会为抽象模型定义。
考虑这种情况。从某处将QMimeData
对象放入视图中。你怎么知道这个数据是否是正确的类型?是谁的工作来决定数据是否属于正确的类型?
在Model-View
框架中,View
仅绘制作品。它由Model
决定如何处理数据,显示什么,什么是可接受的以及什么不是。因此,当View
上放置一段数据时,您需要将其发送到Model
,以检查已删除的数据是否满足Model
的要求。执行此工作的钩子是bool Model::canDropMimeData(...)
。
如果可以接受,那么数据的处理也需要由Model
本身完成。您需要再次将数据发送到Model
。这方面的钩子是bool Model::dropMimeData(...)
。
您如何知道数据是否成功处理?检查返回值!如果数据处理成功,那么您很可能需要更新View
。
因此,除了上面的代码之外,您必须会覆盖接收dragEnterEvent
的{{1}},dragMoveEvent
和dropEvent
,您可以致电View
和canDropMimeData(...)
dropMimeData(...)