我自定义了从QStringListModel继承的数据模型AnnotationListModel
。AnnotationListModel
类的目的,是为数据项添加复选框,实现数据项之间的互斥。
现在,我在QDialog中创建了三个QListView和AnnotationListModel
对象。模型中的数据项作为复选框添加,并且是独占的。
我可以在QListView中选中复选框,但选中的状态无法快速显示。
如何使QListView快速刷新?
class AnnotationListModel :public QStringListModel
{
Q_OBJECT
public:
AnnotationListModel(AnnotationType annType, const QStringList& stringList, QObject* parent = nullptr);
~AnnotationListModel() {};
protected:
Qt::ItemFlags flags(const QModelIndex& index) 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;
signals:
void sendAnnotation(const AnnotationType& annoType, const QString& annotation);
private:
AnnotationType m_annoType;
QStringList m_stringList;
QMap<QString, bool> m_stringList_map; //<annotationName,checked>
};
AnnotationListModel::AnnotationListModel(AnnotationType annType, const QStringList& stringList, QObject* parent)
:QStringListModel(parent), m_stringList(stringList), m_annoType(annType)
{
setStringList(m_stringList);
for (auto& value : m_stringList)
{
m_stringList_map[value] = false;
}
}
Qt::ItemFlags AnnotationListModel::flags(const QModelIndex& index) const
{
if (!index.isValid())
{
return Qt::ItemIsEnabled;
}
return Qt::ItemIsUserCheckable | QStringListModel::flags(index);
}
QVariant AnnotationListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
if (role == Qt::CheckStateRole)
{
if (m_stringList_map[m_stringList.at(index.row())] == true)
{
return Qt::Checked;
}
else
{
return Qt::Unchecked;
}
}
else if (role == Qt::DisplayRole)
{
return m_stringList.at(index.row());
}
return QStringListModel::data(index, role);
}
bool AnnotationListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid())
{
return false;
}
if (role == Qt::CheckStateRole)
{
if (value == Qt::Checked)
{
for (int i{ 0 }; i < m_stringList.size(); ++i)
{
if (i != index.row())
{
m_stringList_map[m_stringList.at(i)] = false;
}
else
{
m_stringList_map[m_stringList.at(i)] = true;
sendAnnotation(m_annoType, m_stringList.at(i));
}
}
}
else if (value == Qt::Unchecked)
{
m_stringList_map[m_stringList.at(index.row())] = false;
}
}
return QStringListModel::setData(index, value, role);
}
字符串
创建三个AnnotationListModel
对象:
switch (itr_kind.key())
{
case AnnotationType::CounCode:
m_counCodeModel = new AnnotationListModel(AnnotationType::CounCode, l_annoStrList);
m_uiDialog->listView_country->setModel(m_counCodeModel);
connect(m_counCodeModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
break;
case AnnotationType::DriSide:
m_driSideModel = new AnnotationListModel(AnnotationType::DriSide, l_annoStrList);
m_uiDialog->listView_driving->setModel(m_driSideModel);
connect(m_driSideModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
break;
case AnnotationType::RoadType:
m_roadTypeModel = new AnnotationListModel(AnnotationType::RoadType, l_annoStrList);
m_uiDialog->listView_road->setModel(m_roadTypeModel);
connect(m_roadTypeModel, &AnnotationListModel::sendAnnotation, this, &AnnotationDialog::sendAnnotation);
}
型
对话框通过mainwindow
打开。
的数据
1条答案
按热度按时间niknxzdl1#
在我看来,你犯了四个错误,但最重要的是前两个:
QStringListModel
)的正确方法是使用代理模型(QAbstractProxyModel
的子类)。它工作得很好,但更容易实现,并且更灵活,因为它可以与任何模型类型一起使用。QMap<...>
容器。我相信这就是代码中大部分计算时间被浪费的地方,特别是在调试模式下测试对话框时(容器有很多很多只在调试中完成的检查,这使得它们的使用速度比发布时慢得多)。
至少,不将检查过的索引保存为
QModelIndex
是正确的。setData
方法发出dataChanged
信号。setData
方法返回false
/true
。准确地说,确实返回了一个布尔值,但仅由QStringListModel::setData(...)
返回,这不是您想要做的。下面的
AnnotationProxyModel
为你想要实现的任何模型实现了排他性的复选框。它派生QIdentityProxyModel
,并通过QPersistentModelIndex
记住选中的索引(与QModelIndex
不同,它可以保存)。我让你检查你是否真的需要保持
Q_OBJECT
宏和你的信号(S)在下面的定义,如果是的,添加他们回来自己。字符串
与任何其他代理模型一样,它是通过使用
QStringListModel
调用setSourceModel(...)
来使用的,即以这种方式:型