Я создал пользовательскую модель, производную от QAbstractItemModel, которая содержит набор XML-данных в древовидной иерархической форме, которые будут отображаться в QTreeView, как показано на следующем рисунке:
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 Model / View, и эта ошибка действительно устрашала меня и заставляла меня чесать голову в течение нескольких дней. Я надеюсь, что кто-то здесь может помочь мне здесь, прежде чем я потеряю все свои волосы! Спасибо!
РЕДАКТИРОВАТЬ: обновить, чтобы включить некоторые исходные коды
Мой тестовый проект имеет два диалоговых окна, по одному 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 с помощью редактирования столбца (пользовательская обработка столбца; я не буду подробно останавливаться) и т. Д. Непосредственно на исходной модели, и она работала как с использованием фильтра сортировки, так и без него. модель. Проблема возникает, когда я пытаюсь удалить «строку», которая является элементом 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 ()?