Ich habe ein sehr spezifisches Problem bei der Verwendung eines QML ListView Elements in Kombination mit seinen Abschnitt Eigenschaften.Qt QML ListView contentHeight Verhalten
Ich verwende Qt 4.8.6, aber ich habe auch das gleiche Problem, wenn ich dies in Qt 5.3.1 versuche.
Der Code kann sie auch durch einfaches Ändern der Import-Anweisung zu
Import 1.0 in älteren Versionen von Qt ausgeführt werden (für < Qt 4.7.4)
oder
QtQuickimportieren QtQuick 1.1 (Für> = Qt 4.7.4)
Hier ist ein eigenständiger Anwendungsfall, mein Problem zu demonstrieren:
import QtQuick 2.2
Rectangle {
width: 800
height: 800
color: "black"
property int pageNumber: 1
property int totalPages: Math.ceil(animalListView.contentHeight/animalListView.height)
Text {
x: 2
y: 90
color: "Orange"
text: "Expected height: " + (animalListView.count*70 + (50*10))
font.pixelSize: 28
}
Text {
x: 2
y: 0
color: "Orange"
text: "Actual ContentHeight: " + animalListView.contentHeight
font.pixelSize: 28
}
Text {
x: 2
y: 30
color: "Orange"
text: "Actual ChildrenRectHeight: " + animalListView.childrenRect.height
font.pixelSize: 28
}
Text {
x: 2
y: 60
color: "Orange"
text: "Total model items (minus sections): " + animalListView.count
font.pixelSize: 28
}
Rectangle {
id: boundingRect
width: 640
height: 500
x: 20
y: 200
radius: 10
border.width: 1
border.color: "green"
color: "transparent"
// The delegate for each section header
Component {
id: sectionHeaderDelegate
Rectangle {
width: parent.width
height: 50 // this is the problem
color: "transparent"
Text {
anchors.left: parent.left
id: headerText
text: section
color: "red"
}
Rectangle {
anchors.fill: parent
border.color: "purple"
border.width: 1
color: "transparent"
}
}
}
ListModel {
id: animalsModel
ListElement { name: "1Parrot"; size: "Small" }
ListElement { name: "2Guinea pig"; size: "Small" }
ListElement { name: "3Dog"; size: "Medium" }
ListElement { name: "4Cat"; size: "Medium" }
ListElement { name: "5Elephant"; size: "Medium" }
ListElement { name: "6Parrot"; size: "Small" }
ListElement { name: "7Guinea pig"; size: "Small" }
ListElement { name: "8Dog"; size: "Medium" }
ListElement { name: "9Cat"; size: "Medium" }
ListElement { name: "10Elephant"; size: "Large" }
ListElement { name: "11Parrot"; size: "Large" }
ListElement { name: "12Guinea pig"; size: "Large" }
ListElement { name: "13Dog"; size: "Large" }
ListElement { name: "14Cat"; size: "Medium" }
ListElement { name: "15Elephant"; size: "Large" }
ListElement { name: "16Parrot"; size: "Small" }
ListElement { name: "17Guinea pig"; size: "Small" }
ListElement { name: "18Dog"; size: "Medium" }
ListElement { name: "19Cat"; size: "Medium" }
ListElement { name: "20Elephant"; size: "Large" }
}
ListView {
id: animalListView
anchors.fill: parent
anchors.margins: 10
clip: true
interactive: true
flickableDirection: Flickable.VerticalFlick
boundsBehavior: Flickable.StopAtBounds
model: animalsModel
delegate: Item {
width: parent.width
height: 70
Text {
text: name
color: "green"
}
Rectangle {
anchors.fill: parent
border.color: "yellow"
border.width: 1
color: "transparent"
}
}
section.property: "size"
section.criteria: ViewSection.FullString
section.delegate: sectionHeaderDelegate
}
}
Rectangle {
anchors.top: boundingRect.top
anchors.left: boundingRect.right
anchors.leftMargin: 20
width: 40
height: 40
color: "blue"
MouseArea {
anchors.fill: parent
onClicked: {
if (pageNumber > 1) {
animalListView.contentY -= animalListView.height;
animalListView.returnToBounds();
--pageNumber;
}
}
}
enabled: (!animalListView.atYBeginning)
visible: !(animalListView.atYBeginning && animalListView.atYEnd)
Text {
anchors.centerIn: parent
font.family: "Wingdings 3"
font.pixelSize: 40
text: "Ç" // Up arrow
}
}
Text {
visible: totalPages > 1
anchors.left: boundingRect.right
anchors.verticalCenter: boundingRect.verticalCenter
width: 100
height: 20
font.pixelSize: 18
horizontalAlignment: Text.AlignHCenter
color: "red"
text: qsTr("%1 of %2").arg(pageNumber).arg(totalPages)
}
Rectangle {
anchors.bottom: boundingRect.bottom
anchors.left: boundingRect.right
anchors.leftMargin: 20
width: 40
height: 40
color: "orange"
MouseArea {
anchors.fill: parent
onClicked: {
if (pageNumber < totalPages) {
animalListView.contentY += animalListView.height;
++pageNumber;
}
}
}
enabled: (!animalListView.atYEnd)
visible: !(animalListView.atYBeginning && animalListView.atYEnd)
Text {
anchors.centerIn: parent
font.family: "Wingdings 3"
font.pixelSize: 40
text: "È" // Down arrow
}
}
}
ich die Listview bin mit einer Liste von Tiermodellen angezeigt werden, die von ihrer Größe klassifizierte. Um diese Kategorisierung in der Ansicht zu erreichen, benutze ich die section.property, section.critiria und section.delegate Eigenschaften des ListView wie im oben angegebenen Code implementiert.
(Hinweis. Bitte ignorieren Sie die Tatsache, dass das Modell, das ich auf dem Listview liefern nicht sortiert ist, ich verstehe, dass dies zahlreiche doppelte Kategorie Einträge in der Listview schaffen Dies ist neben dem Punkt hier.)
Wenn die Anzahl der Modelle den sichtbaren Bereich der ListView überschreitet, verwende ich die Eigenschaft totalPages, um zu berechnen, wie viele volle ListView-Seiten für die Navigation vorhanden sind. Die Pfeil-nach-oben- und die Pfeil-nach-unten-Taste dekrementieren und inkrementieren den content.Y der ListView jeweils um die Höhe des ListView.
Das Problem ist, dass die content des Listview nicht statisch bleibt, dynamisch verändert und bewirkt, dass meine Totalpages Eigenschaft Berechnung falsch.
Es ist interessant zu beachten, dass dieses Verhalten auftritt, wenn und nur wenn ich eine Höhe für meine sectionHeaderDelegate Rechteck festlegen. Wenn ich die height-Anweisung (Höhe: 50) auskommentiere, bleibt die contentHeight der ListView wie erwartet statisch - mit dem Nachteil, dass die Abschnittsüberschriften/Kategorien jetzt über dem Modelltext stehen, was überhaupt nicht sinnvoll ist .
Also meine Frage ist, warum die contentHeight des QML ListView-Elements dynamisch ändert, wenn und nur wenn ich einen Abschnittsdelegaten benutze, dessen Höhe auf einen Wert ungleich Null gesetzt wurde?
Außerdem habe ich die folgenden Eigenschaften im Listview zu Testzwecken verlassen, sollte der Listview mit den Auf-/Ab-Pfeile verwendet werden:
interactive: true flickableDirection: Flickable.VerticalFlick boundsBehavior: Flickable.StopAtBounds
Der Take-Away, den ich aus dem Thread erhalte, zu dem Sie verlinken, ist folgender: "Wenn Elemente in einem vertikalen ListView keine feste Höhe haben, wird contentHeight geschätzt." Ok, aber in meinem Fall haben alle Modellobjekte dieselbe implizite Höhe und der Sektionsdelegat hat auch eine feste Höhe. Ich verwende keine Variablenhöhen für eines meiner Modellelemente oder im Abschnitt delegate, aber ich habe immer noch das gleiche Problem, wenn sich contentHeight dynamisch ändert. – ManuelH
Mein Problem stammt ausschließlich aus der Verwendung des Abschnittsdelegaten. Wenn die Höhe des Delegates auf einen anderen Wert als den impliziten Wert festgelegt wird, wird der Wert contentHeight seltsam berechnet/geschätzt, selbst wenn der Abschnittsdelegat eine feste Höhe hat! – ManuelH
Ihre Abschnittsüberschrift hat eine dynamische Höhe, da sie mit einer Höhe von 50 Pixeln gezeichnet werden kann, wenn sie sich zuerst in der Abschnittsgruppe befindet oder nicht gezeichnet wird, wenn sie nicht das erste Element in der Gruppe ist. Wie gesagt, was passiert, wenn Ihre Sektionen nicht gruppiert werden können - jedes Element fester Größe hat seinen eigenen Kopfbereich fester Größe, so dass nichts dynamisch ist. –