未调用模型中的 QListView moveRow()
QListView moveRow() from model not called
我有一个应该显示图像预览的列表视图。为此,我创建了一个项目 "ListItem"
class ListItem
{
public:
ListItem();
ListItem(QString name, QImage image);
QImage* previewIcon();
void setPreviewIcon(QImage icon);
QImage *image();
void setImage(QImage* image);
void setImage(QImage image);
void setName(QString name);
void setChecked(bool checked);
QString name();
bool checked();
private:
QImage m_preview;
QImage m_image;
QString m_name;
bool m_checked;
};
此模型存储自己的图像及其预览。这适用于插入和删除项目:
class ListModel: public QAbstractListModel
{
Q_OBJECT
public:
ListModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
bool removeRow(int row, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool insertRow(int row, const QModelIndex &parent = QModelIndex());
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool appendItem(ListItem* item);
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild);
Qt::DropActions supportedDropActions() const override;
QHash<int, QByteArray> roleNames() const override;
private:
ListItem* getItem(const QModelIndex &index) const;
private:
QList<ListItem*> m_scannedDocuments;
};
这是 QListView 的设置:
m_scannedDocumentsModel = new ListModel();
m_scannedDocuments = new QListView();
m_scannedDocuments->setModel(m_scannedDocumentsModel);
m_scannedDocuments->setDragDropMode(QAbstractItemView::InternalMove);
m_scannedDocuments->setMovement(QListView::Snap);
m_scannedDocuments->setDefaultDropAction(Qt::MoveAction);
预览、名称以及是否选中都可以拖放。问题是图像 "m_image"。当我在视图中移动时,视图调用 insertRows() 并插入一个新项目并删除旧项目,但不调用 moveRows。
为什么不调用 moveRows()?
在这里您可以找到完整的实现:
ListModel.cpp
ListModel.h
另一种方法是为它自己的图像创建一个 userRole。在这里,我尝试将 roleNames() 重新实现为
QHash<int, QByteArray> ListModel::roleNames() const {
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[Qt::UserRole] = "Qt::UserRole";
return roles;
}
并检查 setdata()/data() 中的角色,但这也不起作用。
拥有复杂模型并在列表视图中移动它们的最佳方法是什么?
如 already answered Qt 兴趣列表中的简要说明:
Because moveRows was added in Qt 5.x, and drag and drop in Qt 4, and still uses insert+remove for backwards compatibility.
我要补充一点,我想 "moveRows" 被认为是 "optimization" 而不是模型的真正要求,并且视图无法知道是否真正实现了移动方法。由于可编辑模型需要 remove/insert 个函数,因此默认调用这些函数是 "safer"。
您可以重新实现模型的 dropMimeData()
方法并自己调用 moveRows()
。但是,需要注意的是,如果你这样做,你应该从方法中 return false
。如果你 return true
到 Qt::MoveAction
,视图仍然会尝试从模型中的旧位置删除行(这显然不是你想要的)。
我有一个应该显示图像预览的列表视图。为此,我创建了一个项目 "ListItem"
class ListItem
{
public:
ListItem();
ListItem(QString name, QImage image);
QImage* previewIcon();
void setPreviewIcon(QImage icon);
QImage *image();
void setImage(QImage* image);
void setImage(QImage image);
void setName(QString name);
void setChecked(bool checked);
QString name();
bool checked();
private:
QImage m_preview;
QImage m_image;
QString m_name;
bool m_checked;
};
此模型存储自己的图像及其预览。这适用于插入和删除项目:
class ListModel: public QAbstractListModel
{
Q_OBJECT
public:
ListModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
bool removeRow(int row, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool insertRow(int row, const QModelIndex &parent = QModelIndex());
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool appendItem(ListItem* item);
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild);
Qt::DropActions supportedDropActions() const override;
QHash<int, QByteArray> roleNames() const override;
private:
ListItem* getItem(const QModelIndex &index) const;
private:
QList<ListItem*> m_scannedDocuments;
};
这是 QListView 的设置:
m_scannedDocumentsModel = new ListModel();
m_scannedDocuments = new QListView();
m_scannedDocuments->setModel(m_scannedDocumentsModel);
m_scannedDocuments->setDragDropMode(QAbstractItemView::InternalMove);
m_scannedDocuments->setMovement(QListView::Snap);
m_scannedDocuments->setDefaultDropAction(Qt::MoveAction);
预览、名称以及是否选中都可以拖放。问题是图像 "m_image"。当我在视图中移动时,视图调用 insertRows() 并插入一个新项目并删除旧项目,但不调用 moveRows。
为什么不调用 moveRows()?
在这里您可以找到完整的实现: ListModel.cpp ListModel.h
另一种方法是为它自己的图像创建一个 userRole。在这里,我尝试将 roleNames() 重新实现为
QHash<int, QByteArray> ListModel::roleNames() const {
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[Qt::UserRole] = "Qt::UserRole";
return roles;
}
并检查 setdata()/data() 中的角色,但这也不起作用。
拥有复杂模型并在列表视图中移动它们的最佳方法是什么?
如 already answered Qt 兴趣列表中的简要说明:
Because moveRows was added in Qt 5.x, and drag and drop in Qt 4, and still uses insert+remove for backwards compatibility.
我要补充一点,我想 "moveRows" 被认为是 "optimization" 而不是模型的真正要求,并且视图无法知道是否真正实现了移动方法。由于可编辑模型需要 remove/insert 个函数,因此默认调用这些函数是 "safer"。
您可以重新实现模型的 dropMimeData()
方法并自己调用 moveRows()
。但是,需要注意的是,如果你这样做,你应该从方法中 return false
。如果你 return true
到 Qt::MoveAction
,视图仍然会尝试从模型中的旧位置删除行(这显然不是你想要的)。