2017-02-27 1 views
0

Ich versuche, eine TabBar erstellt hat Vorschaubilder der verbundenen Layout-Kinder. Nachdem jedoch mehrere Tabs hinzugefügt wurden (die genaue Anzahl hängt von der Anzahl der Elemente in den Tabs ab), gibt QML einen Fehler aus und die PreviewTabBar verliert alle ihre untergeordneten Inhalte.Warum verliert meine benutzerdefinierte TabBar in diesem Beispiel ihren Inhalt untergeordnete Elemente?

Das Folgende ist ein minimales Arbeitsbeispiel:

Mein 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 
    } 
} 

Die PreviewTabBar.qml Vorschauen des Inhalts enthält:

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() 
    } 
} 

und nicht zuletzt die PreviewButton.qml verwendet eine ShaderEffectSource, um die Vorschau zu rendern:

import QtQuick 2.8 
import QtQuick.Controls 2.1 

TabButton { 
    height: 80 
    width: 140 

    function setSource(source) { 
     preview.sourceItem = source 
    } 

    contentItem: ShaderEffectSource { 
     id: preview 
    } 
} 

Dieses Beispiel ruft auf meinem Computer etwa 80 Registerkarten auf, danach verliert die PreviewTabBar alle untergeordneten Registerkarten (nicht das StackLayout). Im Beispiel des realen Lebens mit komplizierteren Tab-Inhalten bekomme ich jedoch nur bis zu 8 Tabs. Was könnte ich falsch machen?

Hier ist der relevante Teil der Anwendung Ausgabe:

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 

Ich habe versucht, die dynamische Erstellung von Bauteilen in einer Callback-Finishing wie hier beschrieben:

http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically

jedoch, dass brough keine Besserung. Hier

ist ein Link zum Beispielprojekt:

https://www.file-upload.net/download-12341284/tabtestshader.zip.html

Antwort

1

Die wahrscheinlichste Ursache ist die Linie 17 in PreviewTabBar.qml der wie folgt lautet:

var item = component.createObject() 

Wie Sie keine Eltern haben festgelegt in der createObject() -Funktion der GarbageCollector neigt dazu, wild zu laufen, und löschen Sie Ihr Objekt, auch wenn es immer noch referenziert wird.
Auch wenn dies nicht dokumentiert ist, sollten Sie immer ein übergeordnetes Objekt übergeben, um sicherzustellen, dass es den GC überlebt.

Ein stabilerer Weg wäre, die Tabs aus einem Modell zu generieren und die entsprechenden Modelleinträge in die addTab-Funktionen hinzuzufügen.

Als kleine Bemerkung auf der Seite: Sie erstellen eine neue Komponente jedes Mal, wenn Sie eine Ihrer addTab-Funktionen aufrufen. Warum deklarieren Sie es nicht einmal wie

Component { 
    id: myComp1 
    ... 
} 

und erstellen Sie die Objekte daraus?

+0

Dies löst das Problem für das Beispiel, danke! Zu Ihrer Frage: Weil ich nicht wusste, dass das möglich ist. :) –

Verwandte Themen