一、Qt Widgets 问题交流
1.
二、Qt Quick 问题交流
1.Repeator 的 delegate 在 remove 移除时的注意事项
Qt Bug Tracker:https://bugreports.qt.io/browse/QTBUG-47500
Repeator 在调用 remove 函数之后,对应的 Item 会立即释放,后续就无法访问上下文的属性了:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: root
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ListModel {
id: list_model
ListElement { value: 1 }
ListElement { value: 2 }
ListElement { value: 3 }
}
Flow {
anchors.fill: parent
Repeater {
id: repeator
model: list_model
delegate: Rectangle {
id: item
width: 100
height: 50
border.color: "black"
Text {
anchors.centerIn: parent
text: model.index
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("before", item.width, repeator.count, model.value)
list_model.remove(model.index, 1)
console.log("after", item.width, repeator.count, model.value)
}
}
Component.onDestruction: {
console.log("free")
}
}
}
}
}
测试代码在调用 remove 后,Component.onDestruction 立即触发了,之后只能访问 item 属性,外部属性以及 model role 无法继续访问了。
但如果把 Repeator 换成 ListView,Component.onDestruction 在 onClicked 执行完后才会触发。
2.非动态创建的对象调用 destroy() 不触发 Component.onDestruction
如下代码调用 destory 后没有触发 Component.onDestruction:
Rectangle {
id: item
width: 300
height: 300
anchors.centerIn: parent
color: "red"
MouseArea {
anchors.fill: parent
onClicked: {
item.destroy()
}
}
Component.onDestruction: {
console.log("item free")
}
}
如果替换成自定义的 C++ 类,在习惯加上打印,会发现析构是执行了的:
#include <QQuickItem>
#include <QDebug>
class CppItem : public QQuickItem
{
Q_OBJECT
public:
explicit CppItem(QQuickItem *parent = nullptr)
: QQuickItem(parent) {
qDebug() << Q_FUNC_INFO;
}
~CppItem(){
qDebug() << Q_FUNC_INFO;
}
};
CppItem {
id: cpp_item
Component.onCompleted: {
console.log("init")
}
Component.onDestruction: {
console.log("free")
}
}
MouseArea {
anchors.fill: parent
onClicked: {
cpp_item.destroy()
}
}
3.View 嵌套的问题
QML 自带的 ListView、GridView、TableView 等,在可视区域和 cacheBuffer 范围外的元素一般是没有在初始化时加载的,只有显示对应的元素时才动态加载。当组合 View 实现更复杂的效果时会有个问题,子级 View 一般需要加载全部内容才能得到这一级的宽高,或者二级嵌套的 Flow + Repeator 等默认就全部加载的组件。当子级 View 内容很多,或者加载了大量图片数据,内存占用就会很高。
这里还有个恶心的地方,无论是 QML 还是 Widgets,View 的相关源码都用到一些未导出的类,这就导致很难直接子类化 C++ View 类然后重写部分接口,要么把相关类都 Copy 一下,要么得改源码重新编译下 Qt 对应模块。