Версия для печати темы
Форум на CrossPlatform.RU _ Qt Модель/Представление _ Тормозит иерархическая модель построенная на QAbstractItemModel (библиотека QT)
Автор: Delphist 20.8.2008, 9:36
Есть иерархическая модель наследуемая от QAbstractItemModel (это библиотека QT), построение модели происходит на основе моего иерархического класса типа:
CMyClass
{
public:
CMyClass();
inline QString getName() const {return m_sName;}
inline CMyClass *getParent() {return m_pOwner;}
inline CMyClass& operator[](QString sKey) {return getProperty(sKey);}
...
void setInt(int v);
void setName(QString v);
...
private:
CMyClass& getProperty(QString sKey);
QHash<QString,CMyClass*> m_Properties;
QString m_sName;
int m_nCode;
CMyClass *m_pOwner;
};
Этот класс передается по указателю в модель, соответственно когда происходят изменения в CMyClass генерятся сигналы. На все эти сигналы ставяться один и тот же слот модели, который всего лишь делает reset.
В моем классе в каком-то из узлов делаются переодические обновления (меняется nCode и sName) приблизительно 60 обновлений в сек, в итоге капитально тормозит я так понимаю TreeView из-за отрисовки, потому как reset заставляет полностью перестраиваться дерево а надо лишь всего, те узлы которые изменились.
Подскажите пожалуйста, из-за чего происходит торможение и как от него збавиться?
Автор: trdm 20.8.2008, 10:07
Как насчет профайлинга?
Автор: Litkevich Yuriy 20.8.2008, 10:54
Цитата(Delphist @ 20.8.2008, 13:36)
приблизительно 60 обновлений в сек
а как человек должен на это смотреть, даже еслиб не тормозило?
Я как пользователь тебяб ногами запинал
Автор: Tonal 20.8.2008, 13:19
Ну так не используй reset.
Модель, при изменении данных, должна генерить сигнал dataChanged.
Тогда вьюшка перерисует только изменившийся элементик.
Автор: Delphist 20.8.2008, 13:34
Цитата(Tonal @ 20.8.2008, 13:19)
Ну так не используй reset.
Модель, при изменении данных, должна генерить сигнал dataChanged
А как его генерить? просто написать
emit dataChanged
или как?
Автор: Tonal 20.8.2008, 13:39
void MyModel::onNodeChange(const CMyClass& node) {
QModelIndex curIndex = indByNode(node);
emit dataChanged(curIndex, curIndex);
}
Где MyModel::indByNode вычисляет индекс в модели по экземпляру.
Автор: Delphist 21.8.2008, 8:27
Цитата(Tonal @ 20.8.2008, 14:39)
Где MyModel::indByNode вычисляет индекс в модели по экземпляру.
Спасибо для onNodeChange indByNode выглядит так:
void MyModel::modelChanged(int nCode, CSharedVariant &Value)
{
QModelIndex curIndex;
// curIndex = indByNode(Value, 0);
// emit dataChanged(curIndex, curIndex);
curIndex = indByNode(Value, 1);
emit dataChanged(curIndex, curIndex);
}
QModelIndex MyMode::indByNode(CSharedVariant& node, int col)
{
if (node.getOwner()) {
int row = indexOf(node.getOwner(), &node);
if (row == -1)
return QModelIndex();
return createIndex(row, col, &node);
}
return QModelIndex();
}
Вроде работает, но в не уверен на 100%.
Возникла еще одна проблема, а как тогда должен выглядить indByNode, если генерится событие onNodeDestroy(CMyClass& node, int col) т.е. удаляется элемент, в качестве node здесь передается удаляем элемент.
Автор: trdm 21.8.2008, 10:13
посмотри сорцы QDirModel. мне помогло.
Автор: Delphist 21.8.2008, 10:25
Цитата(trdm @ 21.8.2008, 11:13)
посмотри сорцы QDirModel. мне помогло.
смотрел не помагло
Автор: Tonal 21.8.2008, 10:31
Открой ассистента и посмотри состав сигналов и защищённых функций QAbstractItemModel.
Там очень интуитивные названия и доходчиво написаны пояснения.
Автор: Delphist 21.8.2008, 11:32
Цитата(Tonal @ 21.8.2008, 11:31)
Открой ассистента и посмотри состав сигналов и защищённых функций QAbstractItemModel.
Там очень интуитивные названия и доходчиво написаны пояснения.
Не понял а при чем здесь сигналы QAbstractItemModel
Автор: Tonal 21.8.2008, 12:58
Например dataChanged - это сигнал объявленный именно в QAbstractItemModel.
Ты его должен сгенерить (emit dataChanged...) когда данные изменяются.
Остальные можешь или тоже руками сгенерить, или, лучше, воспользоваться защищёнными функциями, которые не только его сгенерят но и ещё что-то там сделают (см исходники что именно).
Автор: Delphist 21.8.2008, 13:17
Цитата(Tonal @ 21.8.2008, 13:58)
Остальные можешь или тоже руками сгенерить, или, лучше, воспользоваться защищёнными функциями, которые не только его сгенерят но и ещё что-то там сделают (см исходники что именно).
Кто-нить может подсказать какими лучше пользоваться защищёнными функциями
Автор: trdm 21.8.2008, 16:42
Цитата(Delphist @ 21.8.2008, 14:17)
Кто-нить может подсказать какими лучше пользоваться защищёнными функциями
лучше пользоваться лучше защишенными.
у тебя талант задавать философские вопросы на программисткую тему
Автор: Tonal 21.8.2008, 17:57
Ты ассистент открой и погляди. Если что конкретно будет не понятно - спрашивай.
Автор: Delphist 26.8.2008, 9:05
Цитата(Tonal @ 21.8.2008, 18:57)
Ты ассистент открой и погляди. Если что конкретно будет не понятно - спрашивай.
Как выяснилось в мою модель от класса CMyClass приходит только сигнал, nodeBeforeDestroyed
для обновления своего TreeView в модели, я делаю так:
void MyModel::nodeBeforeDestroyed(int nCode, CMyClass &Value)
{
/*
CMyClass имеет свойство markDeleted, которое = true если экземляр CMyClass'a помечен на удаление,
так вот у данного Value.markDeleted==true
*/
int i = indexOf(Value.getOwner(), &Value);
QModelIndex idx = indByNode(*Value.getOwner());
beginRemoveRows(idx, i, i);
/*
удалять здесь по настоящему Value через delete нельзя т.к. он удаляется самим классом в нужный момент
я всего лишь должен не отображать его в TreeView
*/
endRemoveRows();
}
Приведенный мною код не работает должным образом (для понимания необходимо прочитать коменнтарии
в приведенном коде. Вот я думаю может надо в виртуальных функциях: index, parent и.т.
ввести признак по markDeleted
Автор: Tonal 26.8.2008, 10:09
Что значит "код не работает должным образом"? Что происходит то?
Раз у тебя есть markDeleted, то естественно отображать такие узлы не нужно и флаг должен учитываться.
Ну и кроме того, может ввести сигнал nodeAfterDestroyed - тогда модель удаления будет точно соответствовать Qt-ёвой.
Автор: Delphist 26.8.2008, 11:50
Цитата(Tonal @ 26.8.2008, 11:09)
Что значит "код не работает должным образом"? Что происходит то?
Раз у тебя есть markDeleted, то естественно отображать такие узлы не нужно и флаг должен учитываться.
Ну и кроме того, может ввести сигнал nodeAfterDestroyed - тогда модель удаления будет точно соответствовать Qt-ёвой.
происходит следующее, если есть вот такое дерево:
root
|___child1
|___child2
|___child3
|___child4
|___child5
|``````|
|``````|__child51
|``````|
|``````|__child52
так вот если скажем child4 помечен на удаление т.е markDeleted == true, то в дереве перестает
отображаться не только child4, но и child5 c его детьми.
По поводу того, что необходимо учитывать markDeleted, возникает вопрос как его учитывать и
в каких виртуальных ф-циях QAbstractItem
Автор: Tonal 26.8.2008, 11:59
Помеченный на удаление не должен учитываться в количестве и должен пропускаться в индексе.
Почему у тебя перестаёт отображаться child5 я не в курсе - видимо где-то ошибка.
Автор: Delphist 26.8.2008, 12:24
Цитата(Tonal @ 26.8.2008, 12:59)
Помеченный на удаление не должен учитываться в количестве и должен пропускаться в индексе.
Почему у тебя перестаёт отображаться child5 я не в курсе - видимо где-то ошибка.
Мог бы имена этих ф-ций перечислить, я так понимаю
rowcount
index
parent
еще какие-нить?
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)