программно проверять элементы в QAbstractItemModel/QTreeView

Я пытаюсь использовать выборку (QModelIndexList), чтобы проверить все выбранные элементы QTreeView.

Я использую setData с Qt::CheckStateRole в индексах, и данные кажутся обновленными. Я испускаю сигнал dataChanged, но дерево не перерисовывается (с ролью, заданной в качестве аргумента, и без нее). Это проблема выбора модели?

Это работает, если я делаю beginResetModel, но мое дерево рушится, что нарушает условия сделки.

Как я могу перекрасить свой предмет?

Вот метод, который я добавил в свою модель

void MyModel::checkSelectedItems( const QModelIndexList &checkedIndexes, bool check )
{
    QVector<int> roles = QVector<int>() << Qt::CheckStateRole;
  for ( const QModelIndex &index : checkedIndexes)
  {
      setData(index, check ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
      emit dataChanged(index, index); //), roles);
  }
}

и вызов к нему:

myModel->checkSelectedItems( myTree->selectionModel()->selectedIndexes(), true );

После звонка выделение серое (и уже не синее), но все равно "выделено". Щелчок в любом месте обновляет дерево и правильно показывает отмеченные элементы.


person Denis Rouzaud    schedule 30.08.2018    source источник
comment
После myModel->checkSelectedItems( myTree->selectionModel()->selectedIndexes(), true ); напишите myTree->update();.   -  person scopchanov    schedule 30.08.2018
comment
это, похоже, не решает проблему, также пытался вызвать myTree->update(index) с измененным индексом.   -  person Denis Rouzaud    schedule 30.08.2018
comment
Мне жаль! В данный момент у меня нет дальнейших идей. Я проверю это снова позже.   -  person scopchanov    schedule 30.08.2018
comment
не беспокойтесь, это стоило попробовать, спасибо за подсказку!   -  person Denis Rouzaud    schedule 30.08.2018
comment
также пробовал myTree->viewPort()->update() без особого успеха   -  person Denis Rouzaud    schedule 30.08.2018
comment
myTree->repaint() решил проблему, но я не уверен, что это правильный подход.   -  person Denis Rouzaud    schedule 30.08.2018
comment
В документации по repaint говорится, что почти во всех случаях update() предпочтительнее, так как позволяет Qt оптимизировать скорость и минимизировать мерцание. Но когда update не работает, следует использовать repaint, как вы уже делали.   -  person scopchanov    schedule 30.08.2018


Ответы (1)


Код, который вы показываете, работает в основном нормально, несмотря на то, что он неверен. Пожалуйста, измените вопрос, включив в него случай репродукции. Но да, у кода есть проблемы.

В контракте setData содержится сигнал dataChanged; любой код, в котором dataChanged выдается за пределами setData, указывает на неработающую реализацию модели. Вы должны переместить эмиссию сигнала на MyModel::setData. Единственное другое место, где допустимо излучать dataChanged, — это слот/функтор в прокси-модели, но только тогда, когда слот/функтор подключен к сигналу dataChanged sourceModel.

myTree-›repaint() решил проблему

Вызов repaint() или update() за пределами реализации виджета почти всегда является ошибкой и указывает на то, что виджет либо используется неправильно, либо неправильно реализован. В вашем случае первое: модель setData сломана и не излучает dataChanged.

Вдохновляющие примеры того, как может выглядеть такой тестовый пример, см., например. этот ответ. В двух словах: стремитесь к 100 строкам или меньше, одному файлу, #include <QtWidgets> в начале, без лишнего кода и шаблонов. Сделайте это мило и просто :)

person Kuba hasn't forgotten Monica    schedule 30.08.2018