滚动时Qml Listview项目消失
Qml Listview items disappear when scrolling
我得到了以下带有列表视图的滚动视图:
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: Msg: undefined
qml: Hash: undefined
我从我的 git
自定义组件返回的方法 (QAbstractListModel) 获取模型信息。
这是我的 QAbstractListModel:
header:
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的class,它有以下方法:
Q_INVOKABLE QObject* getCommitsBranch();
QObject *Git::getCommitsBranch()
{
CommitsBranch* files = new CommitsBranch(repo.data());
return files;
}
我在没有滚动视图的情况下得到了相同的行为。
编辑:
如果我使用一个有很多提交的存储库(更多行到列表视图),即使增加 cacheBuffer 也无济于事,如果我滚动得有点快,所有项目都会消失。
这里的问题是,默认情况下,如果您 return 一个 QObject*,它会将所有权转移给 QML。
http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
The exception to this rule is when a QObject is returned from an
explicit C++ method call: in this case, the QML engine assumes
ownership of the object, unless the ownership of the object has
explicitly been set to remain with C++ by invoking
QQmlEngine::setObjectOwnership() with QQmlEngine::CppOwnership
specified.
您必须手动设置 returned 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;
}
我得到了以下带有列表视图的滚动视图:
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: Msg: undefined
qml: Hash: undefined
我从我的 git
自定义组件返回的方法 (QAbstractListModel) 获取模型信息。
这是我的 QAbstractListModel:
header:
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的class,它有以下方法:
Q_INVOKABLE QObject* getCommitsBranch();
QObject *Git::getCommitsBranch()
{
CommitsBranch* files = new CommitsBranch(repo.data());
return files;
}
我在没有滚动视图的情况下得到了相同的行为。
编辑: 如果我使用一个有很多提交的存储库(更多行到列表视图),即使增加 cacheBuffer 也无济于事,如果我滚动得有点快,所有项目都会消失。
这里的问题是,默认情况下,如果您 return 一个 QObject*,它会将所有权转移给 QML。
http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
The exception to this rule is when a QObject is returned from an explicit C++ method call: in this case, the QML engine assumes ownership of the object, unless the ownership of the object has explicitly been set to remain with C++ by invoking QQmlEngine::setObjectOwnership() with QQmlEngine::CppOwnership specified.
您必须手动设置 returned 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;
}