C++ Qml TableView:滚动时崩溃
我的目标是实现一种具有高速数据更新的模拟器。C++ Qml TableView:滚动时崩溃,c++,windows,qt,qml,tableview,C++,Windows,Qt,Qml,Tableview,我的目标是实现一种具有高速数据更新的模拟器。 该应用程序由以下部分组成: 数据模型:它存储数据,并被TableView用作模型 模拟器:每250ms更新整个数据模型的线程 Qml视图:包含用于显示数据的TableView 一旦启动应用程序,我就可以看到TableView中的数据发生了变化,但是如果我尝试使用鼠标滚轮滚动TableView(保持滚动一段时间),就会出现wierd崩溃 我得到的唯一日志如下: QList::at:“索引超出范围”,文件C:\work\build\qt5\u wor
该应用程序由以下部分组成:
- 数据模型:它存储数据,并被TableView用作模型
- 模拟器:每250ms更新整个数据模型的线程
- Qml视图:包含用于显示数据的TableView
我得到的唯一日志如下:
QList::at:“索引超出范围”,文件C:\work\build\qt5\u workdir\w\s\qtbase\include/QtCore/./../src/corelib/tools/QList.h,第510行,断言失败 更有趣的是,我只有在Windows环境下才会发生这种崩溃,而在CentOs机器上我没有收到任何错误 我在这里试图提取我的项目的主要部分,并尽可能地概括它。
请查找下面的代码,或者如果您愿意,您可以从 mydata.h
#ifndef MYDATA_H
#define MYDATA_H
#include <QObject>
class MyData : public QObject
{
Q_OBJECT
Q_PROPERTY(int first READ first WRITE setFirst NOTIFY firstChanged)
Q_PROPERTY(int second READ second WRITE setSecond NOTIFY secondChanged)
Q_PROPERTY(int third READ third WRITE setThird NOTIFY thirdChanged)
public:
explicit MyData(int first, int second, int third, QObject* parent=0);
int first()const {return m_first;}
int second()const {return m_second;}
int third()const {return m_third;}
void setFirst(int v){m_first=v;}
void setSecond(int v){m_second=v;}
void setThird(int v){m_third=v;}
signals:
void firstChanged();
void secondChanged();
void thirdChanged();
private:
int m_first;
int m_second;
int m_third;
};
#endif // MYDATA_H
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QAbstractListModel>
#include <QMutex>
#include "mydata.h"
class DataModel: public QAbstractListModel
{
Q_OBJECT
public:
enum DataModelRoles {
FirstRole = Qt::UserRole + 1,
SecondRole,
ThirdRole
};
//*****************************************/
//Singleton implementation:
static DataModel& getInstance()
{
static DataModel instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
DataModel(DataModel const&) = delete;
void operator=(DataModel const&) = delete;
//*****************************************/
QList<MyData*>& getData(){return m_data;}
void addData(MyData* track);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = FirstRole) const;
protected:
QHash<int, QByteArray> roleNames() const;
private:
QMutex m_mutex;
QList<MyData*> m_data;
DataModel(QObject* parent=0);
};
#endif // DATAMODEL_H
#ifndef SIMULATOR_H
#define SIMULATOR_H
#include <QThread>
class Simulator: public QThread
{
Q_OBJECT
public:
Simulator(QObject* parent=0);
void run() Q_DECL_OVERRIDE;
private:
void createNewData();
void updateExistingData();
int randInt(int from, int to);
};
#endif // SIMULATOR_H
datamodel.h
#ifndef MYDATA_H
#define MYDATA_H
#include <QObject>
class MyData : public QObject
{
Q_OBJECT
Q_PROPERTY(int first READ first WRITE setFirst NOTIFY firstChanged)
Q_PROPERTY(int second READ second WRITE setSecond NOTIFY secondChanged)
Q_PROPERTY(int third READ third WRITE setThird NOTIFY thirdChanged)
public:
explicit MyData(int first, int second, int third, QObject* parent=0);
int first()const {return m_first;}
int second()const {return m_second;}
int third()const {return m_third;}
void setFirst(int v){m_first=v;}
void setSecond(int v){m_second=v;}
void setThird(int v){m_third=v;}
signals:
void firstChanged();
void secondChanged();
void thirdChanged();
private:
int m_first;
int m_second;
int m_third;
};
#endif // MYDATA_H
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QAbstractListModel>
#include <QMutex>
#include "mydata.h"
class DataModel: public QAbstractListModel
{
Q_OBJECT
public:
enum DataModelRoles {
FirstRole = Qt::UserRole + 1,
SecondRole,
ThirdRole
};
//*****************************************/
//Singleton implementation:
static DataModel& getInstance()
{
static DataModel instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
DataModel(DataModel const&) = delete;
void operator=(DataModel const&) = delete;
//*****************************************/
QList<MyData*>& getData(){return m_data;}
void addData(MyData* track);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = FirstRole) const;
protected:
QHash<int, QByteArray> roleNames() const;
private:
QMutex m_mutex;
QList<MyData*> m_data;
DataModel(QObject* parent=0);
};
#endif // DATAMODEL_H
#ifndef SIMULATOR_H
#define SIMULATOR_H
#include <QThread>
class Simulator: public QThread
{
Q_OBJECT
public:
Simulator(QObject* parent=0);
void run() Q_DECL_OVERRIDE;
private:
void createNewData();
void updateExistingData();
int randInt(int from, int to);
};
#endif // SIMULATOR_H
我很高兴与大家分享我自己答案的解决方案,希望它能帮助那些犯同样错误的人 问题的关键在于:
void Simulator::updateExistingData()
{
QList<MyData*> list=DataModel::getInstance().getData();
for(int i=0;i<list.size();i++)
{
MyData* curr=list.at(i);
curr->setSecond(curr->second()+1);
curr->setThird(curr->third()+2);
QModelIndex index=DataModel::getInstance().index(i,0, QModelIndex());
emit DataModel::getInstance().dataChanged(index,index); //ERROR!
}
}
在datamodel.cpp中:
public slots:
void updateGui(int rowIndex);
void DataModel::updateGui(int rowIndex)
{
QModelIndex qIndex=index(rowIndex,0, QModelIndex());
dataChanged(qIndex,qIndex);
}
signals:
void dataUpdated(int row);
Simulator::Simulator(QObject* parent) : QThread(parent)
{
createNewData();
connect(this,SIGNAL(dataUpdated(int)), &DataModel::getInstance(), SLOT(updateGui(int)));
}
...
void Simulator::updateExistingData()
{
QList<MyData*> list=DataModel::getInstance().getData();
for(int i=0;i<list.size();i++)
{
MyData* curr=list.at(i);
curr->setSecond(curr->second()+1);
curr->setThird(curr->third()+2);
QModelIndex index=DataModel::getInstance().index(i,0, QModelIndex());
emit dataUpdated(i);
}
}
在模拟器.h中:
public slots:
void updateGui(int rowIndex);
void DataModel::updateGui(int rowIndex)
{
QModelIndex qIndex=index(rowIndex,0, QModelIndex());
dataChanged(qIndex,qIndex);
}
signals:
void dataUpdated(int row);
Simulator::Simulator(QObject* parent) : QThread(parent)
{
createNewData();
connect(this,SIGNAL(dataUpdated(int)), &DataModel::getInstance(), SLOT(updateGui(int)));
}
...
void Simulator::updateExistingData()
{
QList<MyData*> list=DataModel::getInstance().getData();
for(int i=0;i<list.size();i++)
{
MyData* curr=list.at(i);
curr->setSecond(curr->second()+1);
curr->setThird(curr->third()+2);
QModelIndex index=DataModel::getInstance().index(i,0, QModelIndex());
emit dataUpdated(i);
}
}
在模拟器.cpp中:
public slots:
void updateGui(int rowIndex);
void DataModel::updateGui(int rowIndex)
{
QModelIndex qIndex=index(rowIndex,0, QModelIndex());
dataChanged(qIndex,qIndex);
}
signals:
void dataUpdated(int row);
Simulator::Simulator(QObject* parent) : QThread(parent)
{
createNewData();
connect(this,SIGNAL(dataUpdated(int)), &DataModel::getInstance(), SLOT(updateGui(int)));
}
...
void Simulator::updateExistingData()
{
QList<MyData*> list=DataModel::getInstance().getData();
for(int i=0;i<list.size();i++)
{
MyData* curr=list.at(i);
curr->setSecond(curr->second()+1);
curr->setThird(curr->third()+2);
QModelIndex index=DataModel::getInstance().index(i,0, QModelIndex());
emit dataUpdated(i);
}
}
Simulator::Simulator(QObject*parent):QThread(parent)
{
createNewData();
连接(this,SIGNAL(dataUpdated(int)),&DataModel::getInstance(),SLOT(updateGui(int));
}
...
void模拟器::updateExistingData()
{
QList=DataModel::getInstance().getData();
对于(int i=0;isetSecond(curr->second()+1);
curr->setThird(curr->third()+2);
QModelIndex index=DataModel::getInstance().index(i,0,QModelIndex());
发出数据更新(i);
}
}
使用Signal/Slot方法,我们确信请求将由创建该类的线程(Gui线程)在receiver类中处理,因此下面的dataChanged信号将由适当的线程发出