ListView width inside Repeater
-
Hi all. I am trying to build custom table, that fit to my needs. This is the code:
GridLayout { property var columnName: ["index", "name", "state", "time", "pps", "format"] property var columnWidth: [0.1, 0.4, 0.1, 0.1, 0.1, 0.2] id: grid anchors.fill: parent flow: GridLayout.LeftToRight columns: columnName.length rows: 5 Repeater { id: repeater model: grid.columnName ListView { property int prevCurrentIndex: 0 anchors.fill: parent focus: index === 0 model: refTableModel clip: true implicitWidth: contentItem.childrenRect.width delegate: Text { width: 40 text: model[modelData] } onCurrentIndexChanged: { if (focus !== true) return; var dir = currentIndex - prevCurrentIndex; console.log("direction: " + dir); for (var idx = 0; idx < repeater.count; ++idx) { var item = repeater.itemAt(idx); if (item !== this && item !== null) { if (dir > 0) { item.incrementCurrentIndex(); } else { item.decrementCurrentIndex(); } } } prevCurrentIndex = currentIndex; } } } }
What i want is to setup width of each column (implemented with ListView) accordingly to coefficient, denoting the part of whole GridLayout width. But this width somehow equal to zero, and i don't understand why. How to achieve what i needs?
-
@egor.utsov
Something like this?ApplicationWindow { id: window visible: true width: 640 height: 480 title: qsTr("Hello World") GridLayout { id: grid property var columnName: ["index", "name", "state", "time", "pps", "format"] property var columnWidth: [0.1, 0.4, 0.1, 0.1, 0.1, 0.2] anchors.fill: parent flow: GridLayout.LeftToRight columns: columnName.length rows: 1 Repeater { id: repeater model: grid.columnName ListView { id: list model: 10 clip: true width: grid.columnWidth[index]*window.width height: window.height delegate: Text { width: 40 text: "TEST" + index } } } }
-
@Diracsbracket Thanks! It approach worked, but i am planned to put this table in separate QML file and use it as a component. So i don't have access to
ApplicationWindow
object. What to do in this case. Use root item of QML document instead ofApplicationWindow
? -
@Diracsbracket I checked approach with separate QML doc and it is not working. I try to create table as
Window { width: 256 height: 64 CustomTable { width: parent.width height: parent.height model: Model{} } }
Here,
width
andheight
of root item insideCustomTable
will be equal to zero at the moment, when ListViews created. But if i createCustomTable
like this:CustomTable { width: 256 height: 64 model: Model{} }
it will work. But i don't want to depends on absolute values. How can i deal with it? And why sizes not calculated before constructing child items?
-
@egor.utsov
You can define two propertiesComponent { id: gridComponent GridLayout { id: grid property var columnName: ["index", "name", "state", "time", "pps", "format"] property var columnWidth: [0.1, 0.4, 0.1, 0.1, 0.1, 0.2] property real gridWidth: 10 //dummy value property real gridHeight: 10 //dummy value ..... ListView { id: list ... width: grid.columnWidth[index]*grid.gridWidth height: grid.gridHeight ... } } }//Component
and then in JS for example:
Component.onCompleted: { var myGrid = gridComponent.createObject(someParent, {"gridWidth": someValue, "gridHeight": someValue2}) }
-
@Diracsbracket Where i should catch
onCompleted
event ? Inside component? Below is not workingCustomComponent.qml:
Item { id: root Component.onCompleted {console.log("width = " + root.width);} // width = 0 <-- problem }
Main.qml
Window { width: 256 height: 64 CustomComponent { width: parent.width height: parent.height } }
-
@egor.utsov
If you use the parent'swidth
andheight
properties to set a child's dimensions, then the child'swidth
andheight
are set when the child first becomes visible, and this is done afterComponent.onCompleted()
it seems - theparent
seems to be assigned after the component is completed.So the
console.debug()
in your particular example shows the still uninitialized value. -
@Diracsbracket what to do then?
-
@egor.utsov
For example:Item { anchors.fill: parent id: item property bool ok: (height>0) && (width>0) onOkChanged: { console.debug(item.height + " " + item.width) var comp = Qt.createComponent("CustomComponent.qml") var obj = comp.createObject(this, {"gridWidth": item.width, "gridHeight": item.height}) } }
-
Thanks to @Diracsbracket
Final solution:
Item { property ListModel model property bool timeToBuildTable: (width > 0) && (height > 0) id: root onTimeToBuildTableChanged: { if (timeToBuildTable) { loader.anchors.fill = root; loader.sourceComponent = gridComponent; } } onActiveFocusChanged: loader.item.forceActiveFocus(); Loader { id: loader anchors.fill: parent } Component { id: gridComponent FocusScope { GridLayout { property var columnName: ["index", "name", "state", "time", "pps", "format"] property var columnWidth: [0.1, 0.5, 0.1, 0.1, 0.1, 0.1] id: grid anchors.fill: parent flow: GridLayout.LeftToRight columns: columnName.length rows: 5 rowSpacing: 1 columnSpacing: 1 Repeater { id: repeater model: grid.columnName ListView { property int columnIndex: index property int prevCurrentIndex: 0 id: column model: root.model focus: index === 0 clip: true spacing: 1 Layout.fillHeight: true Layout.fillWidth: true width: root.width * grid.columnWidth[columnIndex] delegate: Rectangle { width: root.width * grid.columnWidth[column.columnIndex] height: root.height / grid.rows Text { text: model[modelData] } } onCurrentIndexChanged: { if (focus !== true) return; var dir = currentIndex - prevCurrentIndex; for (var idx = 0; idx < repeater.count; ++idx) { var item = repeater.itemAt(idx); if (item !== this && item !== null) { if (dir > 0) { item.incrementCurrentIndex(); } else { item.decrementCurrentIndex(); } } } prevCurrentIndex = currentIndex; } } } } } } }