У меня возникает очень специфическая проблема при использовании элемента ListView QML в сочетании с его свойствами раздела.Qt QML ListView contentHeight поведение
Я использую Qt 4.8.6, но у меня также такая же проблема, когда я пытаюсь это сделать в Qt 5.3.1.
Следующий код также может работать в более ранних версиях Qt, просто изменив оператор импорта в
импорт QtQuick 1.0 (Для < Qt 4.7.4)
или
импорт QtQuick 1.1 (для> = Qt 4.7.4)
Вот автономный случай использования, чтобы продемонстрировать мою проблему:
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
}
}
}
Я использую ListView для отображения списка моделей животных, классифицированного по их размеру. Для достижения этой категоризации в представлении я использую раздел .property, section.critiria и раздел.delegate свойства ListView, реализованные в приведенном выше коде.
(Примечание:. Просьба игнорировать тот факт, что модель я поставляю в ListView не отсортирован, я понимаю, что это создаст многочисленные повторяющиеся записи категории в ListView Это рядом с точкой здесь.)
Когда число моделей превышает видимую область ListView, я использую свойство totalPages, чтобы рассчитать, сколько полных страниц ListView доступно для навигации. Стрелки вверх и стрелки вниз просто уменьшают и увеличивают содержимое .Y ListView по высоте ListView соответственно.
Проблема заключается в том, что contentHeight в ListView не остается статичным, она динамически меняется, и причина моего TOTALPAGES расчета свойства быть неправильными.
Интересно отметить, что такое поведение возникает тогда и только тогда, когда я устанавливаю высоту для моего прямоугольника sectionHeaderDelegate. Если я прокомментирую инструкцию высоты (высота: 50), то contentHeight ListView остается статичным, как и ожидалось - с недостатком, что заголовки/категории разделов теперь находятся поверх текста модели, что совсем не полезно ,
Итак, мой вопрос: почему элемент contentHeight элемента QML ListView динамически изменяется тогда и только тогда, когда я использую делегат раздела, высота которого была установлена на ненулевое значение?
Кроме того, я оставил следующие свойства в ListView для целей тестирования, то ListView следует использовать с стрелками вверх/вниз:
interactive: true flickableDirection: Flickable.VerticalFlick boundsBehavior: Flickable.StopAtBounds
Вынос, который я получил из потока, на который вы ссылаетесь, заключается в том, что «когда элементы в вертикальном ListView не имеют фиксированной высоты, оценивается contentHeight». Хорошо, но в моем случае все элементы модели имеют одинаковую неявную высоту, а делегат раздела имеет фиксированную высоту. Я не использую переменную высоту для любого из моих элементов модели или делегата раздела, но у меня все еще есть такая же проблема с динамическим изменением contentHeight. – ManuelH
Моя проблема объясняется исключительно использованием делегата раздела. Установка высоты делегата на что-либо, кроме его неявного значения, приводит к тому, что contentHeight вычисляется/оценивается странно, даже если делегат секции имеет фиксированную высоту! – ManuelH
Заголовок вашего заголовка имеет динамическую высоту, потому что он может быть нарисован с высотой 50 пикселей, если он первый в группе разделов или не будет рисовать, когда он не является первым элементом в группе. Как я уже сказал, посмотрите, что происходит, когда ваши разделы не могут быть сгруппированы - каждый элемент фиксированного размера имеет свой собственный заголовок секции фиксированного размера, так что ничего не динамично. –