【发布时间】:2019-07-19 05:50:12
【问题描述】:
我正在尝试移动 QTableView 的行。我根据this article构建了一个小的MVCE。我可以成功移动行,但是一旦我放下行就会出现奇怪的效果,请参见下面的打印屏幕:
创建了一个新的 row5,而不是将 two 推送到 Row0 和 three 到 Row1
所以正确的结果应该是:
相反,我得到以下不正确的结果:
我一直在尝试通过阅读this source 来解决这个问题,这对于构建和测试模型很有用。除此之外,this 有助于理解提供给QTableView 的参数,但并没有完全解决问题。另外from here对该过程的简短描述有助于阅读,但我的问题仍然存在。最后我发现this interesting source 似乎将Qt::ItemFlags 描述为可能的解决方案,但无法正确地将其与可能的解决方案联系起来。
请看下面最重要的部分代码:
main.cpp
#include <QApplication>
#include <QtGui>
#include <QAbstractItemModel>
#include <QTableView>
#include <QListView>
#include <QAbstractItemView>
#include "newmodel.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList numbers;
numbers << "one" << "two" << "three" << "four" << "five";
QAbstractItemModel *model = new NewModel(numbers);
QTableView *tableView = new QTableView;
tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
tableView->dragDropOverwriteMode();
tableView->setDragEnabled(true);
tableView->setAcceptDrops(true);
tableView->setDropIndicatorShown(true);
tableView->setModel(model);
tableView->setDefaultDropAction(Qt::MoveAction);
tableView->show();
QListView *listView = new QListView;
listView->setDragEnabled(true);
listView->setAcceptDrops(true);
listView->setModel(model);
listView->setDefaultDropAction(Qt::MoveAction);
listView->show();
return a.exec();
}
newmodel.cpp
#include "newmodel.h"
#include <QStringListModel>
#include <QDebug>
NewModel::NewModel(const QStringList &strings, QObject *parent)
: QAbstractListModel(parent)
, stringList(strings)
{}
int NewModel::rowCount(const QModelIndex &parent) const
{
return stringList.count();
Q_UNUSED(parent);
}
QVariant NewModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
if(index.row() >= stringList.size())
return QVariant();
if(role == Qt::DisplayRole || role == Qt::EditRole)
return stringList.at(index.row());
else
return QVariant();
}
QVariant NewModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role != Qt::DisplayRole)
return QVariant();
if(orientation == Qt::Horizontal)
return QString("Column %1").arg(section);
else
return QString("Row %1").arg(section);
}
Qt::ItemFlags NewModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
if(index.isValid())
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
else
return Qt::ItemIsDropEnabled | defaultFlags;
}
bool NewModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.isValid() && role == Qt::EditRole) {
stringList.replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return false;
}
bool NewModel::insertRows(int position, int rows, const QModelIndex &parent)
{
beginInsertRows(QModelIndex(), position, position+rows-1);
for(int row = 0; row < rows; row++) {
stringList.insert(position, "");
}
endInsertRows();
return true;
Q_UNUSED(parent);
}
bool NewModel::removeRows(int position, int rows, const QModelIndex &parent)
{
beginRemoveRows(QModelIndex(), position, position+rows-1);
for(int row = 0; row < rows; ++row) {
stringList.removeAt(position);
}
endRemoveRows();
return true;
Q_UNUSED(parent);
}
Qt::DropActions NewModel::supportedDropActions() const
{
return Qt::CopyAction | Qt::MoveAction;
}
QStringList NewModel::mimeTypes() const
{
QStringList types;
types << "application/vnd.text.list";
return types;
}
QMimeData *NewModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
foreach(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 NewModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
qDebug() << action;
if(action == Qt::IgnoreAction)
return true;
if(!data->hasFormat("application/vnd.text.list"))
return false;
if(column > 0)
return false;
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());
foreach(const QString &text, newItems) {
QModelIndex idx = index(beginRow, 0, QModelIndex());
setData(idx, text);
beginRow++;
}
return true;
}
bool NewModel::dragDropOverwtiteMode() const
{
return false;
}
非常感谢您指出正确的方向并试图阐明此事
【问题讨论】:
标签: c++ qt c++11 qt5 qtableview