Qml Элементы списка исчезают при прокрутке

У меня есть следующий вид прокрутки со списком внутри:

ScrollView{
anchors.fill: parent
ListView{
id: lvCommitsBranch
model: git.getCommitsBranch();
clip: true
delegate: Rectangle {
height: 100
width: parent.width
Text {
anchors.left: parent.left
font.bold: true
text:model.author
id:txtName
}
Text{
anchors.left: parent.left
anchors.top:txtName.bottom
font.pixelSize: 10
text:model.email
id: txtEmail
}
Text {
anchors.left: parent.left
anchors.top:txtEmail.bottom
text: model.message + ' ' + model.hash
id: txtMsg
}
MouseArea{
anchors.fill: parent
onClicked: {
lvCommitsBranch.currentIndex = index;
console.log('Msg: ' + model.message);
console.log('Hash: ' + model.hash);
}
acceptedButtons: Qt.LeftButton | Qt.RightButton
}
}
}
}

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

введите описание изображения здесь

Когда я нажимаю на предметы, которые не исчезли, я получаю undefined на все свойства модели. Когда Mousearea onclick при запуске выдает следующее:

qml: сообщение: не определено

qml: Hash: undefined

Я получаю информацию о модели из метода (QAbstractListModel), который возвращается из моего git пользовательский компонент.

Это мой QAbstractListModel:

заголовок:

class CommitsBranch : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
AuthorRole,
EMailRole,
MsgRole,
DateRole,
HashRole
};
explicit CommitsBranch(QObject *parent = 0);
CommitsBranch(Repository *repo);
public:
virtual int rowCount(const QModelIndex &parent) const override;
virtual QVariant data(const QModelIndex &index, int role) const override;
protected:
// return the roles mapping to be used by QML
virtual QHash<int, QByteArray> roleNames() const override;
private:
QList<Commit> m_data;
QHash<int, QByteArray> m_roleNames;

};

Cpp:

CommitsBranch::CommitsBranch(QObject *parent)
: QAbstractListModel(parent)
{
}

CommitsBranch::CommitsBranch(Repository *repo)
{
m_roleNames[AuthorRole] = "author";
m_roleNames[EMailRole] = "email";
m_roleNames[MsgRole] = "message";
m_roleNames[DateRole] = "date";
m_roleNames[HashRole] = "hash";

/*
here we append the m_data (QList) Items using libgit2 methods
*/

}

int CommitsBranch::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_data.count();
}

QVariant CommitsBranch::data(const QModelIndex &index, int role) const
{
// this function returns the required data
}

QHash<int, QByteArray> CommitsBranch::roleNames() const
{
return m_roleNames;
}

А git — это просто класс, который наследуется от QObject, и у него есть следующий метод:

Q_INVOKABLE QObject* getCommitsBranch();
QObject *Git::getCommitsBranch()
{
CommitsBranch* files = new CommitsBranch(repo.data());
return files;
}

Я получаю такое же поведение без просмотра прокрутки.

РЕДАКТИРОВАТЬ:
Если я возьму репозиторий с большим количеством коммитов (больше строк для просмотра списка), даже увеличение cacheBuffer не поможет, если я прокручу немного быстро, все элементы исчезнут.

2

Решение

Проблема здесь в том, что по умолчанию, если вы возвращаете QObject *, он передает владение QML.

http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership

Исключением из этого правила является случай, когда QObject возвращается из
явный вызов метода C ++: в этом случае механизм QML предполагает
право собственности на объект, если право собственности на объект не имеет
явно установлено, чтобы остаться с C ++, вызывая
QQmlEngine :: setObjectOwnership () с QQmlEngine :: CppOwnership
указано.

Вы должны установить возвращенное владение QObject * вручную, чтобы оно не уничтожалось механизмом QML:

QObject *Git::getCommitsBranch()
{
CommitsBranch* files = new CommitsBranch(repo.data());

QQmlEngine::setObjectOwnership(files, QQmlEngine::CppOwnership)

return files;
}

Обратите внимание, что у вас будет утечка памяти CommitsBranch объект никогда не будет удален. Но, по крайней мере, ваши предметы QML больше не должны исчезать!

РЕДАКТИРОВАТЬ: Как предложено, вы можете сделать что-то вроде этого, чтобы избежать утечки памяти:

// CommitsBranch Constructor
CommitsBranch::CommitsBranch(Repository *repo, QObject *parent) :
QAbstractListModel(parent) { /*stuff*/ }

QObject *Git::getCommitsBranch()
{
// Setting ownership is not necessary if you pass the parent to the QAbstractListModel
CommitsBranch* commits = new CommitsBranch(repo.data(), this);

return files;
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]