这两天使用qt时遇到一个特别奇怪的错误,就是QItemSelectionModel获取QModelIndexList后,该list清空或释放后就报错。
环境是vs2005+qt4.8.5
先附上测试的源码:
class DlgTestSelect : public QDialog
{
Q_OBJECT
public:
DlgTestSelect(QDialog *parent = 0);
~DlgTestSelect();
void initTabView();
private slots:
void onAddBtn();
private:
QStandardItemModel* m_myTabModel;
Ui::DialogTestSelect ui;
};
DlgTestSelect::DlgTestSelect(QDialog *parent)
: QDialog(parent)
{
ui.setupUi(this);
initTabView();
connect(ui.okButton, SIGNAL(clicked()), this, SLOT(onAddBtn()));
}
DlgTestSelect::~DlgTestSelect()
{
}
void DlgTestSelect::initTabView()
{
m_myTabModel = new QStandardItemModel();
QStringList header;
header << tr("Device Name")
<< tr("Device Model")
<< tr("Device IP")
<< tr("Device Port")
<< tr("Device manufacturer");
m_myTabModel->setHorizontalHeaderLabels(header);
m_myTabModel->setColumnCount(5);
ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui.tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui.tableView->setModel(m_myTabModel);
m_myTabModel->setItem(0, 0, new QStandardItem("12"));
m_myTabModel->setItem(0, 1, new QStandardItem("12"));
m_myTabModel->setItem(0, 2, new QStandardItem("12"));
m_myTabModel->setItem(0, 3, new QStandardItem("12"));
m_myTabModel->setItem(0, 4, new QStandardItem("12"));
}
void DlgTestSelect::onAddBtn()
{
QItemSelectionModel *selections = ui.tableView->selectionModel();
QModelIndexList selectedindexes = selections->selectedRows();
}
这样调用onAddBtn()函数后就会报错,错误的内容就是selectedindexes清理的时候有问题。
堆栈信息如下:
> msvcr80d.dll!_free_dbg(void * pUserData=0x00000000, int nBlockUse=198690096) 行1225 + 0x7 字节C++
KernelBase.dll!750e5627()
ITCClientForJKS.exe!_CrtIsValidHeapPointer(const void * pUserData=0x0bd7c550) 行2072C++
ITCClientForJKS.exe!_free_dbg_nolock(void * pUserData=0x0bd7c550, int nBlockUse=1) 行1279 + 0x9 字节C++
ITCClientForJKS.exe!_free_dbg(void * pUserData=0x0bd7c550, int nBlockUse=1) 行1220 + 0xd 字节C++
ITCClientForJKS.exe!operator delete(void * pUserData=0x0bd7c550) 行54 + 0x10 字节C++
ITCClientForJKS.exe!QModelIndex::`scalar deleting destructor'() + 0x21 字节C++
ITCClientForJKS.exe!QList<QModelIndex>::node_destruct(QList<QModelIndex>::Node * from=0x0bcedc6c, QList<QModelIndex>::Node * to=0x0bcedc6c) 行431 + 0x2f 字节C++
ITCClientForJKS.exe!QList<QModelIndex>::free(QListData::Data * data=0x0bcedc58) 行759C++
ITCClientForJKS.exe!QList<QModelIndex>::~QList<QModelIndex>() 行733C++
ITCClientForJKS.exe!DlgTestSelect::onAddBtn() 行66C++
后来查找各种原因,无解!
最后找到selectedRows的源码,在当前类里执行,竟然就好了!代码如下:
void DlgTestSelect::onAddBtn()
{
QItemSelectionModel *selections = ui.tableView->selectionModel();
//QModelIndexList selectedindexes = selections->selectedRows();
QModelIndexList selectedindexes;
//the QSet contains pairs of parent modelIndex
//and row number
QSet< QPair<QModelIndex, int> > rowsSeen;
const QItemSelection ranges = selections->selection();
for (int i = 0; i < ranges.count(); ++i) {
const QItemSelectionRange &range = ranges.at(i);
QModelIndex parent = range.parent();
for (int row = range.top(); row <= range.bottom(); row++) {
QPair<QModelIndex, int> rowDef = qMakePair(parent, row);
if (!rowsSeen.contains(rowDef)) {
rowsSeen << rowDef;
if (selections->isRowSelected(row, parent)) {
selectedindexes.append(m_myTabModel->index(row, 0, parent));
}
}
}
}
return;
}
总结:这个应该是qt自身的问题,之前查找资料,好像很早就有人遇到这种问题,但是好像都没有看到解决办法。没想到目前这个版本问题还在。