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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как работает BeginINsertRow и ему подобные?  (Прочитано 6371 раз)
nvek
Гость
« : Декабрь 24, 2017, 10:40 »

В документации сказано что надо обновление своей структуры заносить в
Код:
beginInsertRow()
addChild()
endInsertRow()
но, если делать
Код:
addChild()
beginInsertRow()
endInsertRow()
или же
Код:
beginInsertRow()
endInsertRow()
addChild()

будет ошибка, даже если это делать в одной и той же функции.
почему? как это работает?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3257


Просмотр профиля
« Ответ #1 : Декабрь 24, 2017, 12:46 »

При удалении, например, перерасчитывается выделенная строка - если она попала в удаленную область (напирмер, удаляем индексы 5-9), то её надо подвинуть на первый индекс после области (или на парента, если области нет) (10й).
Если вы сперва удалите данные, а потом кинете сигнал, то методы index() и parent() для модели будут давать неверные данные - вью запрашивает 10й индекс, а его уже нет (он теперь 5й).
Если вы сперва кинете сигналы, а потом удалите данные, то будет неверно вызвана отрисовка - на момент отрисовки вью считает, что индексов нет, а они ещё есть. Т.е. она отрисует старые данные и не отрисует часть оставшихся.
И это только глядя на QAbstractItemView, в случае того же QTreeView надо пересчитывать внутреннюю таблицу, которая живет в нём.
Записан
nvek
Гость
« Ответ #2 : Декабрь 25, 2017, 13:58 »

понимаю почему, но не понимаю как  Непонимающий
Записан
nvek
Гость
« Ответ #3 : Декабрь 25, 2017, 14:22 »

опять же, есть простой метод:
Код:

//...
emit serv->sg_removeChildren(1, i, pThis);
emit serv->sg_endDeleteRow();

m_childItems.remove(i);
//...


вначале я говорю чтобы обновилась вьюшка, а затем говорю чтобы удалился элемент.
даже когда после begin делать так, чтобы rowCount выводил на элемент меньше, все равно падает.
Почему так нельзя делать , какая причина этому?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Декабрь 25, 2017, 14:42 »

Не надо ничего вьюшке говорить, т.к. модель сама скажет ей. Именно поэтому нужно все делать в правильном порядке с begin/end.
Записан

ArchLinux x86_64 / Win10 64 bit
nvek
Гость
« Ответ #5 : Декабрь 25, 2017, 16:28 »

да, в правильном, не спорю, интересен другой вопрос, как это все происходит?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #6 : Декабрь 26, 2017, 08:39 »

Предположу: т.к. данные в моделе могут вообще не храниться(например таблица умножения). Компилятору нужно понять когда в таблице что то измениться чтобы пересчитать данные для отображения.
begin - сохраняет первоначальное состояние, end - смотрит нужные изменения(если insert то значит только добавляли) и обновляет в отображение только то что изменилось.
можно один refresh - но тогда придется для всех ячеек вызвать получение новых данных и обновлять всю таблицу. Тогда при удалении строк в самом начале(вне видимости виджета) таблица будет смещена.
Записан
nvek
Гость
« Ответ #7 : Декабрь 26, 2017, 13:20 »

смотрю в исходниках как все идет
beginRemoveRow(){если правильно понимаю, там просиходит добавление в стек тех индексов. которые подвержены изменению (те самые индексы, которые мы подали)} посылает сигнал -> emit rowsAboutTobeRemoved(const QModelIndex& parent, int first, int last)
а затем вызывает свой метод
rowsAboutTobeRemoved(const QModelIndex& parent, int first, int last)
смысл такой, что в endRemoveRows()
в конце вызывается метод removeRow() и после него
emit removeRow()

эти сигналы соединены с QAbstractItemViewPrivate
то есть с нашим представлением видимо, внутри этих сигналов
идет запоминание индексов, затем ихнее удаление

но все равно не понимаю, вначале идет begin потом end
все вроде удалилось. дальше я удаляю из своей структуры
m_childItems.remove(i);
поидее , если синхронизировать это с тем, чтобы rowCount показывал на единицу меньше, то все должно работать.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3257


Просмотр профиля
« Ответ #8 : Декабрь 26, 2017, 18:53 »

Ну, если rowCount/index/parent/data будут возвращать новые данные, то всё будет ок:)
Записан
nvek
Гость
« Ответ #9 : Декабрь 28, 2017, 06:47 »

вот у меня не работает. Падает на паренте при перерисовке. в Парент приходит невалидный указатель по валидному индексу.
Как это работает???  Непонимающий  Непонимающий
И это случается я так думаю из-за хавера, который елозит по treeView
Записан
nvek
Гость
« Ответ #10 : Декабрь 28, 2017, 07:06 »

Опять же повторюсь, что при правильном подходе все работает правильно, но мне безумно интересно, почему. Уже второй день мучию исходники qt
Записан
nvek
Гость
« Ответ #11 : Декабрь 28, 2017, 07:58 »

точно знаю, что в этом всем деле, замешан hover
Код:
//qtreeview.cpp QTreeView::drawRow
const bool hoverRow = selectionBehavior() == QAbstractItemView::SelectRows
                  && index.parent() == hover.parent()
                  && index.row() == hover.row();
ведь это именно он вызывает метод парент.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Декабрь 28, 2017, 08:56 »

.. но мне безумно интересно, почему..
Это пройдет. Пользуясь либой вы/мы неизбежно в какой-то мере становимся "пользователями". Т.е. не нужно вдаваться в подробности отчего да почему если все работает как положено. Это нормально, главное не слишком увлекаться, не сваливаться в бездумную жратву чужих классов. Ну найдете, ну осознаете - да, "полезно", но особого понимания это не добавит.
Записан
nvek
Гость
« Ответ #13 : Декабрь 28, 2017, 10:37 »

Возможно ли такое, что все может быть еще связано с таймером?
данные обновляются по таймингу. Таймер же как я прочитал в книге, полностью ассинхронный.
проверял, с евента, мышки до перерисовки вьюшки идет все в одном потоке.
Залезая в исходники qt я только все больше постигаю черную магию
А может быть такое, что сигналы как-то на системных прерываниях работают?
« Последнее редактирование: Декабрь 28, 2017, 11:12 от nvek » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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