为什么我的自定义 TabBar 在此示例中丢失了它的内容 children?
Why does my custom TabBar lose it's content children in this example?
我正在尝试创建一个 TabBar,其中包含已连接布局 children 的预览图像。但是,在添加多个选项卡后(确切数量取决于选项卡中的元素数量)QML 会抛出错误并且 PreviewTabBar 会丢失其所有内容 children.
以下是一个最小的工作示例:
我的main.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
StackLayout {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
}
Timer {
interval: 50; running: true; repeat: true
onTriggered: addTab()
}
function addTab() {
console.log("add Tab")
var component = Qt.createComponent("qrc:/TabContent.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
var item = component.createObject(swipeView)
tabBar.addTab(item)
tabBar.currentIndex = tabBar.contentChildren.length - 1
console.log("current index " + tabBar.currentIndex)
}
header: PreviewTabBar {
id: tabBar
currentIndex: swipeView.currentIndex
}
}
包含内容预览的PreviewTabBar.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabBar {
signal closeCurrentTab
clip: true
background: Rectangle {
color: "white"
}
function addTab(imageSource) {
var component = Qt.createComponent("PreviewTabButton.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
else {
var item = component.createObject()
item.setSource(imageSource)
addItem(item)
}
}
function closeTab() {
console.log("closeTab")
closeCurrentTab()
}
}
最后但同样重要的是 PreviewButton.qml 使用 ShaderEffectSource 渲染预览:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabButton {
height: 80
width: 140
function setSource(source) {
preview.sourceItem = source
}
contentItem: ShaderEffectSource {
id: preview
}
}
这个例子在我的机器上达到了大约 80 个选项卡,之后 PreviewTabBar 失去了它的所有 children(StackLayout 不是这样)。然而,在具有更复杂选项卡内容的现实生活示例中,我最多只能获得大约 8 个选项卡。我可能做错了什么?
这是应用程序输出的相关部分:
qml: current index 99
qml: add Tab
file:///usr/lib/qt/qml/QtQuick/Controls.2/TabButton.qml:65: TypeError: Cannot read property of null
qml: current index 100
qml: add Tab
qml: current index 1
我尝试按照此处所述在回调中完成动态组件创建:
http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically
然而这并没有带来任何改善。
这里是示例项目的link:
https://www.file-upload.net/download-12341284/tabtestshader.zip.html
最可能的原因是 PreviewTabBar.qml
中的第 17 行:
var item = component.createObject()
由于您没有在 createObject()
函数中设置父级,因此 GarbageCollector 往往会 运行 疯狂,并删除您的对象,即使它仍然被引用也是如此。
尽管没有以这种方式记录,但您应该始终传递父对象,以确保它在 GC 中幸存下来。
一种更稳定的方法是从模型生成 Tabs
,并在 addTab
函数中添加相应的模型条目。
顺便说一句:每次调用 addTab
函数时都会创建一个新组件。你为什么不声明一次像
Component {
id: myComp1
...
}
并从中创建对象?
我正在尝试创建一个 TabBar,其中包含已连接布局 children 的预览图像。但是,在添加多个选项卡后(确切数量取决于选项卡中的元素数量)QML 会抛出错误并且 PreviewTabBar 会丢失其所有内容 children.
以下是一个最小的工作示例:
我的main.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
StackLayout {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
}
Timer {
interval: 50; running: true; repeat: true
onTriggered: addTab()
}
function addTab() {
console.log("add Tab")
var component = Qt.createComponent("qrc:/TabContent.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
var item = component.createObject(swipeView)
tabBar.addTab(item)
tabBar.currentIndex = tabBar.contentChildren.length - 1
console.log("current index " + tabBar.currentIndex)
}
header: PreviewTabBar {
id: tabBar
currentIndex: swipeView.currentIndex
}
}
包含内容预览的PreviewTabBar.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabBar {
signal closeCurrentTab
clip: true
background: Rectangle {
color: "white"
}
function addTab(imageSource) {
var component = Qt.createComponent("PreviewTabButton.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
else {
var item = component.createObject()
item.setSource(imageSource)
addItem(item)
}
}
function closeTab() {
console.log("closeTab")
closeCurrentTab()
}
}
最后但同样重要的是 PreviewButton.qml 使用 ShaderEffectSource 渲染预览:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabButton {
height: 80
width: 140
function setSource(source) {
preview.sourceItem = source
}
contentItem: ShaderEffectSource {
id: preview
}
}
这个例子在我的机器上达到了大约 80 个选项卡,之后 PreviewTabBar 失去了它的所有 children(StackLayout 不是这样)。然而,在具有更复杂选项卡内容的现实生活示例中,我最多只能获得大约 8 个选项卡。我可能做错了什么?
这是应用程序输出的相关部分:
qml: current index 99
qml: add Tab
file:///usr/lib/qt/qml/QtQuick/Controls.2/TabButton.qml:65: TypeError: Cannot read property of null
qml: current index 100
qml: add Tab
qml: current index 1
我尝试按照此处所述在回调中完成动态组件创建:
http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically
然而这并没有带来任何改善。
这里是示例项目的link:
https://www.file-upload.net/download-12341284/tabtestshader.zip.html
最可能的原因是 PreviewTabBar.qml
中的第 17 行:
var item = component.createObject()
由于您没有在 createObject()
函数中设置父级,因此 GarbageCollector 往往会 运行 疯狂,并删除您的对象,即使它仍然被引用也是如此。
尽管没有以这种方式记录,但您应该始终传递父对象,以确保它在 GC 中幸存下来。
一种更稳定的方法是从模型生成 Tabs
,并在 addTab
函数中添加相应的模型条目。
顺便说一句:每次调用 addTab
函数时都会创建一个新组件。你为什么不声明一次像
Component {
id: myComp1
...
}
并从中创建对象?