Russian Qt Forum
Май 19, 2024, 04:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Тормозит иерархическая модель построенн  (Прочитано 5088 раз)
Delphist
Гость
« : Август 21, 2008, 13:54 »

Есть иерархическая модель наследуемая от QAbstractItemModel (это библиотека QT), построение модели происходит на основе моего иерархического класса типа:

Код
C++ (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);
&#160; &#160; QHash<QString,CMyClass*> m_Properties;
&#160; &#160;
&#160; &#160; QString&#160; &#160; &#160; &#160; &#160;  m_sName;
&#160; &#160; int&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;  m_nCode;
&#160; &#160; CMyClass&#160; &#160; &#160; *m_pOwner;
};

Этот класс передается по указателю в модель, соответственно когда происходят изменения в CMyClass генерятся сигналы. На эти сигналы ставяться слот модели, который всего лишь делает.
Код
C++ (Qt)
void MyModel::modelChanged(int nCode, CSharedVariant &Value)
{
&#160; &#160; QModelIndex curIndex;
//&#160; &#160; curIndex = indByNode(Value, 0);
//&#160; &#160; emit dataChanged(curIndex, curIndex);
&#160; &#160;
&#160; &#160; curIndex = indByNode(Value, 1);
&#160; &#160; emit dataChanged(curIndex, curIndex);
}
 
 
QModelIndex MyMode::indByNode(CSharedVariant& node, int col)
{
&#160; &#160; if (node.getOwner()) {
&#160; &#160; &#160; &#160; int row = indexOf(node.getOwner(), &node);
&#160; &#160; &#160; &#160; if (row == -1)
&#160; &#160; &#160; &#160; &#160; &#160; return QModelIndex();
&#160; &#160; &#160; &#160; return createIndex(row, col, &node);
&#160; &#160; }
&#160; &#160; return QModelIndex();
}
 
Работает, но возникла еще одна проблема, а как тогда должен выглядить indByNode, если генерится событие onNodeDestroy(CMyClass& node, int col) т.е. удаляется элемент, в качестве node здесь передается удаляем элемент.
« Последнее редактирование: Август 25, 2008, 09:09 от Delphist » Записан
Tonal
Гость
« Ответ #1 : Август 21, 2008, 17:35 »

С удалением просто последовательность нужно другую.
Сначала генерим сигнал об удалении, а потом реально удаляем данные.
Записан
Delphist
Гость
« Ответ #2 : Август 21, 2008, 21:57 »

С удалением просто последовательность нужно другую.
Что значит последовательность другую?

Сначала генерим сигнал об удалении, а потом реально удаляем данные.
Так у меня так и делается но так надо потом (после удаления) сообщить об этом представлению (TreeView в данном случае) перерисоваться если вызывать reset то это слишком наклодно, поэтому я вызываю emit dataChanged ток не знаю индексы какие?
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #3 : Август 21, 2008, 22:40 »

Цитировать
Так у меня так и делается но так надо потом (после удаления) сообщить об этом представлению (TreeView в данном случае) перерисоваться если вызывать reset то это слишком наклодно, поэтому я вызываю emit dataChanged ток не знаю индексы какие?

Я так понял, что вместо сигналов при добавлении/удалении лучше пользоваться конструкциями beginInsertRows(), endInsertRows() и т.д.

Вот пример - у меня внутреннее представление списка, унаследованного от  QAbstractListModel, лежит в списке QList<QString> table. Когда я добавляю в конец списка новую запись, я делаю таг

Код:
  // Начинаются добавляться данные
  beginInsertRows(QModelIndex(), table.size(), table.size() + 1);

  // Новая запись размещается в списке
  table << tmpline;

  // Добавление данных закончено, далее вид должен сам знает что надо
  // обновить на экране чтоб была видно новая строка
  endInsertRows();

А когда удаляю запись, делаю таг (i - 'это номер записи которую надо удалить)

Код:
 // Начинается удаление записи
 beginRemoveRows(QModelIndex(),i,i);

 // Удаляется элемент
 table.takeAt(i);

 // Удаление записи закончено
 endRemoveRows();

То есть идея такая - указываем какая область меняется, потом эти области будут автоматом перерисованы видом. Так как это будет происходить с вызовом метода data(), который в моем случае из внутреннего представления (из списка table) возвращает запрошенный элемент, то вид как раз и обновится в соответсвии с изменениями, вносимыми в внутренне представление даннх.
Записан

Собираю информацию по крупицам
http://webhamster.ru
Delphist
Гость
« Ответ #4 : Август 22, 2008, 12:17 »

нет. дело в том что у меня класс CMyClass генерит сигнал о том, что с ним происходит на разных этапах, например, происходит удаления child'a тогда, генериться сигнал childDestroyed, далее модель ставит на этот сигнал слот onNodeDestroy(CMyClass& node, int col) и ловит этот сигнал. теперь вопрос что я должен написать здесь чтобы обновлялось не все дерево а только та часть которая дейстительно нуждается в этом, а иначе появляются тормоза
Записан
Tonal
Гость
« Ответ #5 : Август 22, 2008, 12:43 »

Вызвать соответствующие begin*Rows(), end*Rows() для индекса удаляемого элемента.
Ты ассистент читать будешь, или в форумах канючить предпочитаешь?  Злой
Записан
Delphist
Гость
« Ответ #6 : Август 26, 2008, 15:49 »

Вызвать соответствующие begin*Rows(), end*Rows() для индекса удаляемого элемента.
Ты ассистент читать будешь, или в форумах канючить предпочитаешь?  Злой
Как выяснилось в мою модель от класса CMyClass приходит только сигнал, nodeBeforeDestroyed
для обновления своего TreeView в модели, я делаю так:
Код
C++ (Qt)
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
Что значит "код не работает должным образом" - происходит следующее, если есть вот такое дерево:
root
|___child1
|___child2
|___child3
|___child4
|___child5
|``````|
|``````|__child51
|``````|
|``````|__child52
так вот если скажем child4 помечен на удаление т.е markDeleted == true, то в дереве перестает
отображаться не только child4, но и child5 c его детьми.
По поводу того, что необходимо учитывать markDeleted, возникает вопрос как его учитывать и
в каких виртуальных ф-циях QAbstractItemModel
« Последнее редактирование: Август 26, 2008, 17:04 от Delphist » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.099 секунд. Запросов: 19.