У меня есть свой собственный подкласс QAbstractTableModel. Когда в него вставляются новые данные — я выдаю beginInsertRows / endInsertRows, а затем dataChanged с правильными индексами. rowCount, кажется, изменен, хорошо, поскольку я вижу, что скроллер появляется и растет, но …. columnCount нет.
Последовательность такая:
1) Я заполняю модель ДО того, как вставить ее в табличное представление. Этот способ просмотра ловит нужное количество столбцов.
2) Сначала я вставляю модель в представление, затем заполняю ее данными. В этом случае, даже после того, как dataChanged выпущен, представление не будет показывать что-либо, потому что кажется, что оно все еще думает, что нет никаких столбцов. (coulmnCount () возвращает правильную сумму — я проверял несколько раз)
Из того, что я прочитал в документации Qt, не похоже, что мне нужно вручную вызывать beginInsertColumns для большинства моделей … почему тогда представление не может выбрать количество столбцов, когда модель получает данные?
P.S. Во втором случае вызов после заполнения модели:
view->setModel(0);
view->setModel(model);
устанавливает правильное значение счетчика столбцов, но это ужасно …
UPD:
Я обнаружил, что излучающий
emit headerDataChanged(Qt::Horizontal, 0 , columnCount());
действительно исправляет проблему с колонкой, но в документах говорится, что я не должен …….. 🙂
Архитектура модельного представления имеет семантику, которая, к сожалению, не очень хорошо описана в документации. Позвольте мне попытаться изложить основные правила. Определения:
Изменения данных: существующий элемент был изменен.
Структурные изменения: добавлены / удалены строки / столбцы.
Интервал структурных изменений: интервал между вызовами begin[Insert|Delete][Rows|Columns]()
а также end[Insert|Delete][Rows|Columns]()
и между звонками на beginResetModel()
а также endResetModel()
,
С этими определениями должно выполняться следующее. Это зависит от модели и представления реализации, чтобы уважать эти правила. Если одна сторона нарушает правила, другая сторона имеет неопределенное поведение. Таким образом, если вы, как модель, ведете себя в соответствии с правилами, вы можете ожидать, что представление будет придерживаться их. Если модель нарушает правила, представление также может нарушать правила, и наоборот.
dataChanged
Сигнал испускается в существующих строках | столбцах, и его смысл в том, что ранее измененные данные были изменены. Бессмысленно сразу генерировать его в строках | столбцах, которые были только что добавлены | удалены, поскольку представление прекрасно знает, что оно должно прочитать эти данные, если оно того пожелает. Сигнал не должен излучаться в течение интервала структурных изменений, так как представление не имеет возможности реагировать на него — см. № 3 ниже.
Строка | столбец считается добавленной | только удаленной после модель называется end[Insert|Delete][Rows|Columns]()
,
Представление не обращается к модели в течение интервала структурных изменений.
Структурные изменения могут только быть сделано внутри интервал структурных изменений.
Изменения данных могут быть только быть сделано вне интервал структурных изменений.
Все непостоянные индексы действительны только в не замужем интервал между интервалы структурных изменений.
Все непостоянные индексы недопустимы в течение интервала структурных изменений. Это простой результат недоступности модели в течение интервала структурных изменений: какие бы индексы у вас ни были, они все равно бесполезны.
Все непостоянные индексы становятся недействительными после начала интервала структурных изменений.
[row|column]Count(index)
Вызов с допустимым индексом остается постоянным, за исключением периода структурных изменений, который затрагивает элементы с index
,
Значение invalidated
Индекс состоит в том, что представление больше не может использовать этот индекс, это неопределенное поведение, если это так.
Я догадываюсь, что ваша модель не следует одному или нескольким из приведенных выше правил, поэтому представление может вести себя неправильно. Это опасно. Технически, представление может нанести ядерный удар или отформатировать ваш жесткий диск. Не воспринимай это легко 🙂
Если вы заполняете свою модель сразу всеми данными, вы можете просто вызвать reset () внутри вашей модели. Но не стоит вызывать метод reset () каждый раз, когда добавляется новая строка, особенно для больших объемов данных …
Я думаю, что необходимо вызывать beginInsertColumns (), если ваша модель пуста при назначении ее представлению.
В качестве альтернативы вы можете использовать переменную-член, содержащую количество столбцов, которое инициализируется перед передачей модели в представление и вернуть ее из columnCount ().
Я думаю, что причина того, почему в документации Qt чаще всего упоминается beginInsertRows, заключается в том, что она встречается гораздо чаще. Дело в том, что вам нужно вызывать beginInsertColumns () и endInsertColumns () при переопределении insertColumns (). Также вам необходимо повторно реализовать rowCount () и columnCount (). dataChanged (…) только уведомляет представление об изменениях только в существующих строках / столбцах.