我已經創建了一個定製的QAbstractItemModel派生模型,該模型包含一系列樹狀分層結構的XML數據,並將顯示在QTreeView中,如圖所示:當通過源模型函數從源模型中刪除一行時,QSortFilterProxyModel崩潰
http://imageshack.us/photo/my-images/840/xmltreeview.png
這種模式已經成功通過MODELTEST以及一些基本的編輯測試。但是,在嘗試對此模型進行一些篩選時,我遇到了一些問題,以便將模型分成幾個不同的視圖。我試過QSortFilterProxyModel,它崩潰了很多。在嘗試從模型中刪除一行後,它仍會崩潰。
控制檯應用程序顯示這些消息時,會發生崩潰:
ratbr QModelIndex(0,0,0xd162000,CGHXmlModel(0xb197e68))0 0
RR QModelIndex(0,0,0xd162000,CGHXmlModel(0xb197e68) )0 0
,這是當事故發生的調用堆棧:
0 QSortFilterProxyModelPrivate::index_to_iterator qsortfilterproxymodel.cpp 193 0x0134714b
1 QSortFilterProxyModel::parent qsortfilterproxymodel.cpp 1654 0x0111a677
2 QModelIndex::parent qabstractitemmodel.h 389 0x6a2ad95e
3 QPersistentModelIndex::parent qabstractitemmodel.cpp 347 0x6a1f7320
4 QItemSelectionRange::isValid qitemselectionmodel.h 108 0x01341ea4
5 QItemSelectionModel::isSelected qitemselectionmodel.cpp 1187 0x010f0b58
6 QTreeView::drawRow qtreeview.cpp 1602 0x010db133
7 QTreeView::drawTree qtreeview.cpp 1441 0x010da4f4
8 QTreeView::paintEvent qtreeview.cpp 1274 0x010d9bed
9 QWidget::event qwidget.cpp 8333 0x00c1492d
10 QFrame::event qframe.cpp 557 0x00f8e6bc
11 QAbstractScrollArea::viewportEvent qabstractscrollarea.cpp 1043 0x0101bf0f
12 QAbstractItemView::viewportEvent qabstractitemview.cpp 1619 0x010a5785
13 QTreeView::viewportEvent qtreeview.cpp 1256 0x010d9aa3
14 QAbstractScrollAreaPrivate::viewportEvent qabstractscrollarea_p.h 100 0x01276a13
15 QAbstractScrollAreaFilter::eventFilter qabstractscrollarea_p.h 116 0x0127506c
16 QCoreApplicationPrivate::sendThroughObjectEventFilters qcoreapplication.cpp 847 0x6a1ffc73
17 QApplicationPrivate::notify_helper qapplication.cpp 4392 0x00bc96e5
18 QApplication::notify qapplication.cpp 4361 0x00bc9586
19 QCoreApplication::notifyInternal qcoreapplication.cpp 732 0x6a1ff9dc
20 QCoreApplication::sendSpontaneousEvent qcoreapplication.h 218 0x0123d53e
我還是很新的Qt的模型/視圖編程和這個錯誤真的有令人望而生畏,讓我撓了腦袋好幾天。我希望在這裏有人能夠幫我在這裏失去我的頭髮!謝謝!
編輯:更新,包括一些源代碼
我的測試項目有兩個對話框窗口,每一個QTreeView則。一個是包含QAbstractItemModel派生類成員的主窗口,另一個是包含QSortFilterProxyModel派生類成員的子窗口。子窗口還有一個指向實際模型的QAbstractItemModel指針。
主窗口:
class CGHXMLModelDialog : public QDialog
{
Q_OBJECT
...
private:
Ui::CGHXMLModelDialog *ui;
CGHXmlModel* m_mainModel;
CGHXMLParameterDialog* m_ParamDialog;
...
}
子窗口:
class CGHXMLParameterDialog : public QDialog
{
Q_OBJECT
...
private:
void setupProxyModel();
Ui::CGHXMLParameterDialog* ui;
QAbstractItemModel* m_coreModel;//A CGHXMLModel
CGHXMLSortFilterProxyModel* m_ParamModel;
...
}
在CGHXMLModelDialog構造:
m_mainModel = new CGHXmlModel(theDomDocument, this);
ui->CGHXMLTreeView->setModel(m_mainModel);
//Create sub-dialog window containing proxy filter model
m_ParamDialog = new CGHXMLParameterDialog(m_mainModel, this);
然後調用setupProxyModel()方法:
CGHXMLParameterDialog::CGHXMLParameterDialog(QAbstractItemModel* coreModel, QWidget *parent) :
QDialog(parent),
ui(new Ui::CGHXMLParameterDialog),
m_coreModel(coreModel)
{
ui->setupUi(this);
setupProxyModel();
}
void CGHXMLParameterDialog::setupProxyModel()
{
m_ParamModel = new CGHXMLSortFilterProxyModel(this);
m_ParamModel->setSourceModel(m_coreModel);
m_ParamModel->setFilterRegExp(QRegExp("Parameter"));
m_ParamModel->setFilterKeyColumn(0);
m_ParamModel->setDynamicSortFilter(true);
ui->CGHXMLParamView->setModel(m_ParamModel);
}
我測試過插入行,編輯行內容,通過列編輯插入XML屬性(自定義列操作;我不會詳細說明)等等,直接在源模型上工作,它既可以使用也可以不使用Sort-Filter模型。當我試圖刪除一個「行」時,這個問題就出現了,當我的模型中有一個XML元素時,會附加一個Sort-Filter模型。
這裏是我的removeRows代碼:
bool CGHXmlModel::removeRows(int rowposition, int rows, const QModelIndex &parent)
{
CGHXMLTreeItem *parentItem = getItem(parent);
bool success = false;
beginRemoveRows(parent, rowposition, rowposition + rows - 1);
success = parentItem->removeChildren(rowposition, rows);
endRemoveRows();
if(success)//Works!
{
emit layoutChanged();
}
return success;
}
這是由一個按鈕事件處理程序的主窗口調用:
void CGHXMLModelDialog::on_deleteRowButton_clicked()
{
QModelIndex currIndex = ui->CGHXMLTreeView->selectionModel()->currentIndex();
if(!m_mainModel->removeRow(currIndex.row(), currIndex.parent()))
{
qDebug() << "Fail to remove row from Model.";
return;
}
}
//Program crashes after this function returns.
更新:這是錯誤的發出layoutChanged()沒有發佈layoutAboutToBeChanged()?
你可以發佈代碼的一部分(加上相關的周邊線)你刪除行嗎? –
我已添加相關代碼。 – ksming
查看QSortFilterProxyModel和QAbstractItemModel和文檔的實現代碼後,我只是意識到在發佈layoutChanged()之前,我沒有在removeRows/removeColumns中發佈layoutAboutToBeChanged()。我想知道這是否是問題?但是再一次,我從來沒有見過任何例子在removeRows函數中發出任何信號,並且仍然完美地工作。 :( – ksming