Qml, update gridview inside listview item - qt

I have a listview in which, each item has gridview inside it:
ListView{
id:list_roi
anchors.fill: parent
delegate: roi_item_view
model: roi_item_model
spacing: 5
clip: true
focus: true
ScrollBar.vertical: ScrollBar {}
onCurrentIndexChanged: {
valueUpdater.selected_roi_changed(list_roi.currentIndex)
}
highlight: Rectangle {
color: 'lightgray'
}
}
ListModel{
id:roi_item_model
ListElement {roi_rows: 2, roi_cols: 2, roi_subregion_model : [{_text:"555.3"},{_text:"555.3"},{_text:"555.3"}]}
}
Component{
id:roi_item_view
MouseArea {
anchors.fill: parent
onClicked: list_roi.currentIndex = index
}
GridLayout{
id:layout_wrapper
anchors.fill: parent
rows: 3
columns: 5
GridView {
id:grid_sub_region
Layout.row: 2
Layout.column: 0
Layout.columnSpan:5
Layout.alignment: Qt.AlignHCenter
width: roi_cols * 30; height: roi_rows * 30
cellWidth: 30; cellHeight: 30
visible : true
model: roi_subregion_model
delegate: contactsDelegate
focus: true
}
Component {
id: contactsDelegate
CellBox{
id: wrapper
width: 30
height: 30
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
id: contactInfo
text: _text
}
}
}
}
}
as you can see, inside model i have 3 property (roi_rows, roi_cols, roi_subregion_model) which are supposed to change the view of Gridview's rows, columns and data inside each cell, when i change them.
but when i change these values, number of cells inside Gridview does not changes. when i initialize roi_rows and toi_cols to 2 i will have 2x2 gridview after listview item is created. but after initialization i cannot change it. it seems i have to do something to refresh the UI of specific item inside Listview so that the Gridview inside that item will be redrawn.
Update
based on comments: width and height of the GridView will be set based on roi_rows, roi_cols which are part of Listview Model. and because the CellWidth and CellHeight are constant then number of cells (rows and columns of the Gridview) will be changed.

OK i found the answer. in Model,View,Delegate structure when we create a Delegate and want to bind it with a key inside Model, in some cases like 'text' for 'Label' it will be automatically bound automatically. in this example:
ListModel{
id:roi_item_model
ListElement {label_text:"Hello" ,roi_rows: 2, roi_cols: 2, roi_subregion_model : [{_text:"555.3"},{_text:"555.3"},{_text:"555.3"}]}
}
Component{
id:roi_item_view
MouseArea {
anchors.fill: parent
onClicked: list_roi.currentIndex = index
}
GridLayout{
id:layout_wrapper
anchors.fill: parent
rows: 3
columns: 5
Label{ text:label_text }
GridView {
id:grid_sub_region
Layout.row: 2
Layout.column: 0
Layout.columnSpan:5
Layout.alignment: Qt.AlignHCenter
width: roi_cols * 30; height: roi_rows * 30
cellWidth: 30; cellHeight: 30
visible : true
model: roi_subregion_model
delegate: contactsDelegate
focus: true
}
Component {
id: contactsDelegate
CellBox{
id: wrapper
width: 30
height: 30
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
id: contactInfo
text: _text
}
}
}
}
}
label_text inside Model will be bound to text property of Label automatically which means if i change label_text the content of Label will be changed automatically. but for some property we should do this binding manually. in out example add this to delegate of ListView:
Binding {
target: grid_sub_region
property: 'height'
value: roi_rows * 30
}
Binding {
target: grid_sub_region
property: 'width'
value: roi_cols * 30
}

Related

Increment QML property of top-level type in child type

I'm new to Qt with QML. I'm trying to set a property at the top element called buttonIndex so that the child elements could change the property by incrementing the value in the Button element to make the name go from "Device 1" -> "Device 15". This is my QML code below:
Page {
id: page_device
width: 1024
height: 600
property int buttonWidth: 170;
property int buttonHeight: 100;
property int buttonIndex: 1;
header: Label {
id: label_header_devices
text: qsTr("Devices")
font.pixelSize: Qt.application.font.pixelSize * 2
padding: 20
}
Item {
id: item_devices
width: 300
height: 200
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Column {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 10
Repeater {
id: item_devices_rows
model: 3
Row {
spacing: 10
Repeater {
id: item_devices_columns
model: 5
Button {
id: button_device_
width: buttonWidth
height: buttonHeight
text: qsTr("Device ") + page_device.buttonIndex++
Material.foreground: Material.Pink
enabled: false
hoverEnabled: false
// onClicked: Material.background = Material.Teal
}
}
}
}
}
}
}
The output I'm getting is unwanted. I get "Device 107", "Device 108", "Device 109" etc.. I need to have it go from 1-15. I tried using the signal itemAdded in the code and re-assigning the value of the buttonIndex to increment by 1 each time but that didn't work either. And also I need to store that buttonIndex for the Button type such like "item_device_button_1". Any ideas how this can be solved?
As #folibis mentioned, you don't need to create your own property for this. Repeaters (and ListViews, etc.) give delegates access a property called index that already does exactly what you want. The index is 0-based, so if you want it to start at '1', then just add +1.
Repeater {
Button {
text: qsTr("Device ") + (index + 1)
}
}

How to have a numerical model start at 1 in a combobox from QML

In the combobox from qml we can give them a model with a numerical value.
The options of the combobox then start from 0 to the model value minus 1.
What i want is to show the values on the combobox plus 1.
But still, if i try to access, with qml javascript, the value that is selected in that combobox is the original value, what i mean is, if it's the first option it's the value 0. The numbers shall only start from 1 in the display part of combobox.
I'm going to give an example (with a model=32):
display of the combobox
the options:
what i want is them to start at one, like this:
The code used was the following:
import QtQuick 2.9
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
title: "Stack"
visible: true
height: 200
width: 400
Item {
id: page
anchors.fill: parent
width:parent.width
height: parent.height
Column{
width:parent.width
spacing:10
ComboBox {
id:comboBox
model: 32
objectName: "test"
implicitHeight: 30
displayText: currentText
// delegate:
// Button {
// id:buttonCombo
// width: parent.width
// text: index+1
// height:40
// contentItem: Text {
// text: buttonCombo.text
// font: comboBoxCustom.font
// leftPadding: 5
// horizontalAlignment: Text.AlignLeft
// verticalAlignment: Text.AlignVCenter
// elide: Text.ElideRight
// }
// background: Rectangle {
// color: buttonCombo.hovered ? (buttonCombo.pressed ? "#d8d8d8" : "#e8e8e8" ) : "#fff"
// }
// }
anchors.topMargin: 10
}
}
}
}
Maybe this could be done:
displayText: Number(currentText)+1
but i don't know if its the best solution...

QML: TableView dynamic change row height

I have a table of 4 columns, in one of which is text. When you change the width of the column, the width of the internal text also changes. In some cases, the width of the text becomes rather small and the text begins to increase its height (text wrap). How can I increase the height of the row in which this text is located?
This is a column with text
TableViewColumn {
id: fullNameColumn
property int minColWidth: 175
property int maxColWidth: 500
role: "fullName"
title: "ФИО"
width: 360
property string imageSource : ""
onWidthChanged: {
if (width < minColWidth)
width = minColWidth
}
delegate: Rectangle{
id: rowCellContentFullName
color: "transparent"
Text {
property int maxColWidth: 400
id: labelFullName
objectName: "labelFullName"
font.pixelSize: 13
wrapMode: Text.Wrap
anchors.leftMargin: 38
anchors.left: parent.left
horizontalAlignment: styleData.textAlignment
anchors.verticalCenter: parent.verticalCenter
visible: parent.visible
width: parent.width - this.anchors.leftMargin * 2
text: styleData.value !== undefined ? styleData.value : ""
color: "#474747"
renderType: Text.NativeRendering
}
}
This is the rowDelegate
property Component rowDelegate: Rectangle {
id: rowDel
objectName: "RowDelegate"
height: parent.parent.children[1].children[2].children[0].children[0].height < 50 ? 50 : parent.parent.children[1].children[2].children[0].children[0].height
property color selectedColor: styleData.hasActiveFocus ? primaryColor : secondaryColor
property bool selectionMaskVisible
property bool selected: false
}
In rowDelegate Im binding height with terrible expression, but it works. Works only for column 3 (where FullName). If i drag this column in another space my code doesnt work.
Can I change rows height in TableView QML without this terrible expressions? Mb You know some way to solve this problem?
Rostislav.
I had the same problem.
My solution:
TableView {
id: skillsGroupSkills
model: root.updated ? skillsProxy : null
property var rects: ({})
TableViewColumn {
title: "ID"
role: "id"
width: 30
}
TableViewColumn {
id: skillColumn
title: "Название"
role: "skill"
width: 200
}
TableViewColumn {
title: "Sort"
role: "sort_id"
width: 60
}
itemDelegate: Item {
Text {
id: text
color: styleData.textColor
elide: styleData.elideMode
text: styleData.value
width: parent.width
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
onContentHeightChanged: {
if (styleData.column === 1 && styleData.row !== -1) {
var id = skillsGroupsSkillsTableModel.get(skillsProxy.mapRowToSource(styleData.row))["id"]
var rect = skillsGroupSkills.rects[id];
if (rect) rect.height = contentHeight;
}
}
}
}
rowDelegate: Rectangle {
id: rect
Component.onCompleted: {
var id = skillsGroupsSkillsTableModel.get(skillsProxy.mapRowToSource(styleData.row))["id"]
skillsGroupSkills.rects[id] = rect;
}
}
}
In this example I'm dynamically changing second column height in each row.
Every rowDelegate rectangle is saving in the rects property.
My model has unique value in every row - id. I used it to ident rectangles because I have proxyModel. Probably you can use styleData.row directly.
P.S. Yes, I know that this question was in a year ago. May be my solution will be useful for somebody. :)

Dynamically create page based on ListModel count

I am a beginner QT/QML app development
How can I create a qml dynamically based on the ListModel count.
In the view I am listing the modelObjects in a GridLayout using Repeater.
Item{
id:griditem
anchors.fill:parent
GridLayout{
id: grid2
x:145
y:30
Layout.preferredHeight: 480
Layout.preferredWidth: 1135
rowSpacing:10
columnSpacing:40
columns: 3
rows: 2
Repeater{
id: repeater_Id
model: FeatureModel{}
Loader{
id: loader_Id
source: "QuadTiles.qml"
onLoaded: {
loader_Id.item.nIndex=index
loader_Id.item.type_String = type
loader_Id.item.title_Text.text = title
loader_Id.item.description_Text.text = description
loader_Id.item.btn1_icon.source = icon1
}
}
} //Repeater
}//GridLayout
}
Edit :
I am facing some issues
I need to create new views dynamically based on the ModelList count. Each page having maximum 6 item (3 rows and 2 columns) in GridLayout
'QuadTiles.qml' is the qml file which is load in to each item of GridLayout
Try something like this:
lm is the ListModel that is to be split.
SwipeView {
width: 200
height: 800
clip: true
currentIndex: 0
Repeater {
model: Math.ceil(lm.count / 6)
delegate: ListView {
width: 200
height: 800
property int viewIndex: index
model: DelegateModel {
model: lm
groups: DelegateModelGroup { name: 'filter' }
Component.onCompleted: {
for (var i = viewIndex * 6; i < lm.count && i < (viewIndex * 6) + 6; i++) {
items.setGroups(i, 1, ['items', 'filter'])
}
}
filterOnGroup: 'filter'
delegate: Rectangle {
width: 180
height: 30
border.width: 1
Text {
anchors.centerIn: parent
text: index
}
}
}
}
}
}
And don't use a Loader as a delegate. The delegates are instantiated dynamically, so the Loader is just useless overhead. You might use a Loader within your delegate for parts, that are usually not shown.

qml listview improve speed of changing items

i have a listview, how to change a speed of changing items, tried highlightMoveSpeed(highlightMoveDuration), but that does not working
Is there any way to increase the spped
slider.qml
import QtQuick 1.0
Rectangle {
id: slider
anchors.fill: parent
Component {
id: pageDelegate
Rectangle {
id: page
height: parent.height
Component.onCompleted: page.width = slider.width
Rectangle {
anchors.fill: parent
// anchors.margins: 15
Image{
anchors.top: parent.top
anchors.fill: parent
source: modelData
}
}
}
}
ListView {
id: list_model
anchors.fill: parent
model: modelData
delegate: pageDelegate
orientation: ListView.Horizontal
snapMode: ListView.SnapToItem
spacing: 5
highlightMoveSpeed: 10000000
}
}
You can either use the default highlight and set its speed, e.g.
highlightMoveDuration : 200
highlightMoveVelocity : 1000
or, in case you use your custom highlight, let the highlight component handle the behaviour. E.g.
// Set the highlight delegate. Note we must also set highlightFollowsCurrentItem
// to false so the highlight delegate can control how the highlight is moved.
highlightFollowsCurrentItem: false
highlight: Rectangle {
y: myListView.currentItem.y;
Behavior on y {
SmoothedAnimation {
easing.type: Easing.Linear
duration:200;
maximumEasingTime:300
velocity : 1000
}
}
}
Check the qt highlight example
A note about the other highlight move property: if you want to use highlightMoveDuration instead of highlightMoveVelocity (highlightMoveSpeed in Qt 4), you need to set the latter to -1:
highlightMoveDuration: 1000
highlightMoveVelocity: -1

Resources