Russian Qt Forum

Qt => Qt Quick => Тема начата: Гурман от Апрель 22, 2019, 18:10



Название: [РЕШЕНО] Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Апрель 22, 2019, 18:10
Есть у меня QML ListWidget, который связан с QQuickWidget (см. предыдущую тему (http://www.prog.org.ru/topic_32374_0.html) с примером). Сейчас он заполняется, всё работает. Но список не постоянный - элементы могут удаляться и добавляться. Сейчас не ясно как корректно обрабатывать эти изменения списка чтобы не было memory leak и избыточного копирования. То есть после такой привязки:

Код:
    QList<QObject*> notebook;
.....
    rootContext()->setContextProperty("SomeList",QVariant::fromValue(notebook));
    setSource(QUrl("qrc:/listview.qml")); // здесь заданы параметры отображения ListView

Нужно ли что-то делать с QQuickWidget в котором это происходит, или с контекстом, или ещё с чем-нибудь, если содержимое notebook[] меняется?

И сразу ещё такой вопрос - если необходимо изменить отображение списка, достаточно ли установить другой

    setSource(QUrl("qrc:/listview2.qml"));

в котором элементы списка изображаются иначе? Или это надо делать по-другому?


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: clingerwinger от Апрель 23, 2019, 15:10
Цитировать
Нужно ли что-то делать с QQuickWidget в котором это происходит, или с контекстом, или ещё с чем-нибудь, если содержимое notebook[] меняется?
Правильно будет вообще на сторону QML прокидывать модель. Унаследоваться от QAbstractListModel и сделать все как в документации. Если этот вариант не устраивает то может прокатить следующее:
* обновить контекстное свойство так же через setContextProperty;
* сказать вьюхе что модель изменилась, например view.modelChanged();

Цитировать
И сразу ещё такой вопрос - если необходимо изменить отображение списка
Правильно будет изменить делегат у вьюхи и использовать для этого Component {}


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Апрель 23, 2019, 15:38
Цитировать
И сразу ещё такой вопрос - если необходимо изменить отображение списка
Правильно будет изменить делегат у вьюхи и использовать для этого Component {}
Мне это надо делать из C++ кода. Я не знаю другой способ поменять делегата, кроме как подставить другой .qml файл, в котором такой же ListView имеет делегата с другими параметрами.


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: clingerwinger от Апрель 23, 2019, 18:12
Описываете делегаты, желательно в отдельных файлах. Там где вью лежит объявляете их в качестве компонент:

Код:
...
ListView {
    id: view
    ...
    delegate: defaultComponent
}
...
Component
{
    id: defaultComponent
    DefaultDelegate {
        // Здесь можно объявлять дополнительные свойства, например onClicked: {...}
    }
}

Component
{
    id: awesomeComponent
    AwesomeDelegate { }
}
Далее можно менять свойство delegate у вьюхи и указывать нужные идентификаторы компонент.

По поводу вызова из C++: тут в целом зависит от приложения и архитектуры, но самый быстрый наколеночный вариант - пробросить указатель на некий QObject в сторону QML так же через setContextProperty и на стороне QML ловить сигналы через Connections:
Код:
Connections {
    target: myContextPropertyObject
    onMySignal: {
        if (signalParametr == true) {
            view.delegate = awesomeComponent;
        }
    }
}


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Апрель 23, 2019, 22:43
Примерно понятно. Ещё бы примеров толковых, а то в документации нет нифига.


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: clingerwinger от Апрель 24, 2019, 12:16
Вполне себе отличная статья (https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html).


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Май 07, 2019, 23:11
Что-то я влип в какую-то непонятку... Как написано в статье по ссылке из предыдущего сообщения, передёргиваю QQmlContext::setContextProperty() при изменении модели:

Код:
void MainList::receiveSheet(QList<QObject*>& sheet)
{
    rootContext()->setContextProperty("MainList",QVariant::fromValue(sheet));
    setSource(QUrl( sortview[sortOrder] ));
}

если список изменился только внутри, то есть переставлены элементы при сортировке, или если в список добавлены новые элементы - всё нормально, работает как ожидается. Но если в списке удалён элемент, то падает где-то внутри setContextProperty(). Qt собран без отладочной информации, не могу посмотреть что не так происходит внутри него. Вижу только в отладчике что сам список в порядке. Более того - перед передачей функции receiveSheet() он сохраняется в файл в текстовом виде, каждая запись сохраняется поэлементно - и там всё нормально. Это подтверждается тем, что при перезапуске приложения список загружается и корректно отображается - после этого же вызова receiveSheet(). Но падает после удаления элемента упорно в одном месте и на ПК, и на Android девайсе, значит ошибка не наведённая (типа порчи стека или кучи). И не имеет отношения к старым модулям из сборок - на ПК впервые собрал с отладчиком. Падает при любой длине списка - и при 0-й, и при не 0-й. Но самое обидное, что вчера... всё работало. Сегодня только добавил одно поле QString в модель, все остальные действия были с другими частями проекта, не влияющими на эту.

Добавляются элементы в список
Код:
    collection.insert( collection.begin(), new element(item, this) ); // this задаёт в элементе родителя
удаляются соответственно
Код:
    delete collection.takeAt( index );
то есть, ничего особенного. Если не вызывать setContextProperty(), то все внутренние функции со списком нормально работают, то есть он явно консистентен.

Вообще из-за чего в принципе может падать setContextProperty()? Поковырял ещё - в отладчике видно что падает внутри QQmlDelegateModel::release(QObject*), вокруг него неизвестные вызовы.


Название: Re: Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Май 08, 2019, 13:35
С удалением падение не связано, проехали...


Название: Re: [РЕШЕНО] Как корректно отражать изменения списка в ListWidget?
Отправлено: Гурман от Май 27, 2019, 23:29
up...

Увы, поторопился. Всё-таки проблема с удалением. Чтобы не путать - создам отдельную тему.