Russian Qt Forum
Март 29, 2024, 17:40
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Вопросы новичков
>
Как работает BeginINsertRow и ему подобные?
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Как работает BeginINsertRow и ему подобные? (Прочитано 6371 раз)
nvek
Гость
Как работает BeginINsertRow и ему подобные?
«
:
Декабрь 24, 2017, 10:40 »
В документации сказано что надо обновление своей структуры заносить в
Код:
beginInsertRow()
addChild()
endInsertRow()
но, если делать
Код:
addChild()
beginInsertRow()
endInsertRow()
или же
Код:
beginInsertRow()
endInsertRow()
addChild()
будет ошибка, даже если это делать в одной и той же функции.
почему? как это работает?
Записан
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3257
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #1 :
Декабрь 24, 2017, 12:46 »
При удалении, например, перерасчитывается выделенная строка - если она попала в удаленную область (напирмер, удаляем индексы 5-9), то её надо подвинуть на первый индекс после области (или на парента, если области нет) (10й).
Если вы сперва удалите данные, а потом кинете сигнал, то методы index() и parent() для модели будут давать неверные данные - вью запрашивает 10й индекс, а его уже нет (он теперь 5й).
Если вы сперва кинете сигналы, а потом удалите данные, то будет неверно вызвана отрисовка - на момент отрисовки вью считает, что индексов нет, а они ещё есть. Т.е. она отрисует старые данные и не отрисует часть оставшихся.
И это только глядя на
QAbstractItemView
, в случае того же QTreeView надо пересчитывать внутреннюю таблицу, которая живет в нём.
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #2 :
Декабрь 25, 2017, 13:58 »
понимаю почему, но не понимаю как
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #3 :
Декабрь 25, 2017, 14:22 »
опять же, есть простой метод:
Код:
//...
emit serv->sg_removeChildren(1, i, pThis);
emit serv->sg_endDeleteRow();
m_childItems.remove(i);
//...
вначале я говорю чтобы обновилась вьюшка, а затем говорю чтобы удалился элемент.
даже когда после begin делать так, чтобы rowCount выводил на элемент меньше, все равно падает.
Почему так нельзя делать , какая причина этому?
Записан
kuzulis
Джедай : наставник для всех
Offline
Сообщений: 2812
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #4 :
Декабрь 25, 2017, 14:42 »
Не надо ничего вьюшке говорить, т.к. модель сама скажет ей. Именно поэтому нужно все делать в правильном порядке с begin/end.
Записан
ArchLinux x86_64 / Win10 64 bit
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #5 :
Декабрь 25, 2017, 16:28 »
да, в правильном, не спорю, интересен другой вопрос, как это все происходит?
Записан
deMax
Хакер
Offline
Сообщений: 600
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #6 :
Декабрь 26, 2017, 08:39 »
Предположу: т.к. данные в моделе могут вообще не храниться(например таблица умножения). Компилятору нужно понять когда в таблице что то измениться чтобы пересчитать данные для отображения.
begin - сохраняет первоначальное состояние, end - смотрит нужные изменения(если insert то значит только добавляли) и обновляет в отображение только то что изменилось.
можно один refresh - но тогда придется для всех ячеек вызвать получение новых данных и обновлять всю таблицу. Тогда при удалении строк в самом начале(вне видимости виджета) таблица будет смещена.
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #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
Сообщений: 3257
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #8 :
Декабрь 26, 2017, 18:53 »
Ну, если rowCount/index/parent/data будут возвращать новые данные, то всё будет ок:)
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #9 :
Декабрь 28, 2017, 06:47 »
вот у меня не работает. Падает на паренте при перерисовке. в Парент приходит невалидный указатель по валидному индексу.
Как это работает???
И это случается я так думаю из-за хавера, который елозит по treeView
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #10 :
Декабрь 28, 2017, 07:06 »
Опять же повторюсь, что при правильном подходе все работает правильно, но мне безумно интересно, почему. Уже второй день мучию исходники qt
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #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
Сообщений: 11445
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #12 :
Декабрь 28, 2017, 08:56 »
Цитата: nvek от Декабрь 28, 2017, 07:06
.. но мне безумно интересно, почему..
Это пройдет. Пользуясь либой вы/мы неизбежно в какой-то мере становимся "пользователями". Т.е. не нужно вдаваться в подробности отчего да почему если все работает как положено. Это нормально, главное не слишком увлекаться, не сваливаться в бездумную жратву чужих классов. Ну найдете, ну осознаете - да, "полезно", но особого понимания это не добавит.
Записан
nvek
Гость
Re: Как работает BeginINsertRow и ему подобные?
«
Ответ #13 :
Декабрь 28, 2017, 10:37 »
Возможно ли такое, что все может быть еще связано с таймером?
данные обновляются по таймингу. Таймер же как я прочитал в книге, полностью ассинхронный.
проверял, с евента, мышки до перерисовки вьюшки идет все в одном потоке.
Залезая в исходники qt я только все больше постигаю черную магию
А может быть такое, что сигналы как-то на системных прерываниях работают?
«
Последнее редактирование: Декабрь 28, 2017, 11:12 от nvek
»
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...