How to get model in onCurrentItemChanged with QtQuick ListView - qt

I use the listview like this:
ListView {
id: list
clip: true
spacing: 2
anchors.fill: parent
model: datas
delegate: listItem
onCurrentItemChanged: {
//I want get the part of the model which belong to currentItem
}
}
Component {
id: listItem
Rectangle {
height: 30
anchors.left: parent.left
anchors.right: parent.right
color: "green"
Label {
anchors.fill: parent
text: uuid
color: "white"
}
MouseArea{
anchors.fill: parent;
onClicked: {
console.log("study clicked")
console.log(uuid)
studyList.currentIndex=index
//component.selected(uuid)
}
}
}
}
I want get the part of the model which belong to currentItem in onCurrentItemChanged.
For example:
the model is
ListModel{
ListElement{uuid:aaaa}
ListElement{uuid:bbbb}
ListElement{uuid:cccc}
}
So there should be 3 item.
If I click the second one, I can get the ListElement which uuid is bbbb.
Is there any way?

You can do:
onCurrentIndexChanged: {
//I want get the part of the model which belong to currentItem
console.log(datas.get(currentIndex))
}
then the code will be
Item{
width: 800
height: 480
ListModel{
id: datas
ListElement{uuid:"aaaa"}
ListElement{uuid:"bbbb"}
ListElement{uuid:"cccc"}
}
ListView {
id: list
clip: true
spacing: 2
anchors.fill: parent
model: datas
delegate: listItem
onCurrentIndexChanged: {
//I want get the part of the model which belong to currentItem
console.log(datas.get(currentIndex).uuid)
}
}
Component {
id: listItem
Rectangle {
height: 30
anchors.left: parent.left
anchors.right: parent.right
color: "green"
Label {
anchors.fill: parent
text: uuid
color: "white"
}
MouseArea{
anchors.fill: parent;
onClicked: {
list.currentIndex=index
}
}
}
}
}
or you can try this approach, when button clicked emit a signal with parameters, the current element and the index or only the element .
example:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Item{
width: 800
height: 480
ListModel{
id: datas
ListElement{uuid:"aaaa"}
ListElement{uuid:"bbbb"}
ListElement{uuid:"cccc"}
}
ListView {
id: list
clip: true
spacing: 2
anchors.fill: parent
model: datas
delegate: listItem
signal sgnElementClicked(var element, var index)
// onCurrentIndexChanged: {
// //I want get the part of the model which belong to currentItem
// console.log(currentItem)
// }
onSgnElementClicked: console.log(element.uuid, index)
}
Component {
id: listItem
Rectangle {
height: 30
anchors.left: parent.left
anchors.right: parent.right
color: "green"
Label {
anchors.fill: parent
text: uuid
color: "white"
}
MouseArea{
anchors.fill: parent;
onClicked: {
// console.log("study clicked")
//console.log(uuid)
list.sgnElementClicked(datas.get(index), index)
/// studyList.currentIndex=index
//component.selected(uuid)
}
}
}
}
}

Related

Can QML StackLayout detect drag from a component outside itself

I have a StackLayout with 3 stack items (2 static and one dynamically generated) which switches on button click. I want to make the second and third stack items a Droparea (third one is dynamically created) where I want to drag items from a Listview which is outside the StackLayout. Is it possible or I am doing something wrong?
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page{
id: pageid
width: parent.width
height: parent.height
Row{
id: row1
Button{
text: "0"
onClicked: layout.currentIndex = 0
}
Button{
text: "1"
onClicked: layout.currentIndex = 1
}
Button{
text: "2"
onClicked:{
var str = 'import QtQuick 2.15; Rectangle {id: rect2; color: "red"; DropArea{anchors.fill: parent; onEntered: {rect2.color = "silver"}}}'
var comp = Qt.createQmlObject(str,layout,"dynamicSnippet1")
onClicked: layout.currentIndex = 2
}
}
}
// Stacklayout block
StackLayout {
id: layout
anchors.top: row1.bottom
height: parent.height - row1.height - dragger.height
width: parent.width
currentIndex: 0
// Component 0
Rectangle {
id: rect0
color: 'teal'
}
// Component 1
Rectangle {
id:rect1
color: 'plum'
DropArea{
anchors.fill: parent
onEntered: {rect1.color = "gold"}
}
}
}
// Drag rectangles
ListView{
id: dragger
anchors.top: layout.bottom
height: 30
width: parent.width
orientation: Qt.Horizontal
model: 3
delegate: Rectangle{
id: xrect
height: 30
width: 60
color:"grey"
border.width: 1
border.color: "orange"
MouseArea{
id: ma
anchors.fill: parent
onReleased: parent.Drag.drop()
drag.target: parent
}
}
}
}
You forgot to set property Drag.active for your draggable target, e.g. put statement
Drag.active: ma.drag.active
into your xrect to make it work.
In addition you could check more dragging signals in your DropArea:
onDropped: console.error("# dropped")
onContainsDragChanged: console.error("# containsDrag", containsDrag)

How to update or read TextFiled inside GridLayout which is in TabView

I have below stack of components and I want to read and set value of the TextFiled:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Rectangle
--------------------TextField <--- I want to access this TextField
I have also a case where I need to access Repeater inside the Tab:
-Rectangle
-----TabView
---------Tab
-----------Rectangle
--------------GridLayout
------------------Repeater
--------------------TextField <--- I want to access this TextField also
I have tried to access it using:
var tab0 = myTabView.getTab(0);
tab0.children[0].text = "Some Text"; // I get Undefined Error
I have tried to access the component using a function inside the Tab:
import QtQuick 2.0
import QtQuick.Controls 2.14 as QQC2
import QtQuick.Layouts 1.14
import QtQuick.Controls 1.4 as QQC1
QQC2.Item {
QQC1.TabView {
QQC1.Tab {
title: "tab1"
function printValue () {
console.log("myTextFld.txt: "+myTextFld.txt); // <-- Getting Error myTextFld undefined.
}
Rectangle {
id: tabHolderRext
color: "blue"
GridLayout {
id: myGrid
model: 7
Repeater {
id: herderRepeater
model: header
delegate: Rectangle {
TextField {
// I want to Access This TextField also
}
}
}
Rectangle {
id: row0Rect
Layout.row: 0
Layout.column: index
TextFiled {
id: myTextFld
text: modelData
}
}
// Rest of the rows
}
}
}
}
}
Item id can be used to access the values from TextField if you have all items in same qml file. If you have different qml files then make use of alias types link to access the values.
Repeater case: The Textfield has to update the underlying modelview --> model first then we can make use of the model's data.
Here is a sample code. I have stacked all item's in the same qml file so that access by id works here.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
Item {
anchors.fill: parent
anchors.margins: 10
TabView {
anchors.fill: parent
Tab {
title: "TextField"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
Rectangle {
height: 40
width: 150
TextField {
id: inputId
anchors.fill: parent
placeholderText: "enter text"
}
}
Button {
height: 40
width: 150
text: "show txt"
onClicked: labelId.text = inputId.text
}
Rectangle {
height: 40
width: 150
Label {
id: labelId
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
Tab {
title: "Repeater"
Item {
anchors.fill: parent
Grid {
spacing: 20
anchors.fill: parent
anchors.margins: 10
columns: 3
ListModel {
id: fruitModel
ListElement { name: "Apple" }
ListElement { name: "Orange" }
ListElement { name: "Banana" }
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
TextField {
anchors.fill: parent
text: name
onTextChanged: fruitModel.setProperty(index, "name", text) // update model data
}
}
}
Repeater {
width: parent.width
height: parent.height / 2
model: fruitModel
delegate: Rectangle {
height: 40
width: 150
Label {
text: name
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}

How to have the components comunicate between them in an accordion like Component? [duplicate]

I'm trying to create accordion qml control like this.
First I thought that I can use combobox and customize it but now I think it is impossible.
Is there any standerd control that I can use? If not can you help me with controls structure?
Just playing with QML
PanelItem.qml
import QtQuick 2.7
import QtQuick.Layouts 1.2
Item {
default property var contentItem: null
property string title: "panel"
id: root
Layout.fillWidth: true
height: 30
Layout.fillHeight: current
property bool current: false
ColumnLayout {
anchors.fill: parent
spacing: 0
Rectangle {
id: bar
Layout.fillWidth: true
height: 30
color: root.current ? "#81BEF7" : "#CEECF5"
Text {
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: root.title
}
Text {
anchors{
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 10
}
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
text: "^"
rotation: root.current ? "180" : 0
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.current = !root.current;
if(root.parent.currentItem !== null)
root.parent.currentItem.current = false;
root.parent.currentItem = root;
}
}
}
Rectangle {
id: container
Layout.fillWidth: true
anchors.top: bar.bottom
implicitHeight: root.height - bar.height
clip: true
Behavior on implicitHeight {
PropertyAnimation { duration: 100 }
}
}
Component.onCompleted: {
if(root.contentItem !== null)
root.contentItem.parent = container;
}
}
}
usage:
import QtQuick 2.7
import QtQuick.Layouts 1.2
import QtQuick.Window 2.0
Window {
visible: true
width: 400
height: 400
ColumnLayout {
anchors.fill: parent
spacing: 1
property var currentItem: null
PanelItem {
title: "Panel 1"
Rectangle {
color: "orange"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 2"
Rectangle {
color: "lightgreen"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 3"
Rectangle {
color: "lightblue"
anchors.fill: parent
}
}
PanelItem {
title: "Panel 4"
Rectangle {
color: "yellow"
anchors.fill: parent
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
What about using this open source component which I did here
Accordion component and used here Accordion component example.
You only need to initialize:
Components.Accordion {
id: acordion
anchors.fill: parent
anchors.margins: 10
}
And create the data dynamically like this:
propertyAcordion.model = [
{
'menuTitle': value,
'children': [
{
'menuTitle': value,
'children': [
...
Updating the MouseArea click part as below with some added condition. Thanks to folibis for this qml accordian menu.
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.current = !root.current;
if(root.parent.currentItem !== null) {
if(root.parent.currentItem !== root)
root.parent.currentItem.current = false;
}
root.parent.currentItem = root;
}
}

How to get the list of QML Column Layout children?

I am working on some QML + c++ project and, I have a little problem with QML layouts:
I have two custom components :
First one: is a side-bar "SideTabBar.qml" (the purple rectangle in the image below).
Second one: is the element in the side-bar "SideBarElement.qml".
This image describes what I am talking about:
What I want is: highlight each side bar element on click.
To do so I am trying to iterate over the columnLayout children and lowlight them excepting the clicked one. But, I have not managed to make it works.
SideTabBar.qml:
Item {
id: sideTabBar
width: 70
height: parent.height
property string activeElement: ""
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
SideBarElement{elementId:"a1";image:"../assets/product.svg"}
SideBarElement{elementId:"a2";image:"../assets/product.svg"}
Item {Layout.fillHeight: true}
}
}
SideBarElement.qml:
Item {
property alias image: sideBarElementicon.source
property string elementId: ""
id: sideBarElement
width:parent.width
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
Rectangle{
anchors.fill: parent
color:Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
MouseArea{
anchors.fill: parent
onClicked:{ sideTabBar.activeElement = elementId
// compiler does not even enter this loop.
// for(var child in Layout.children){
// console.log("this is a child")
// }
}
}
}
In this case it is better to work with a Repeater since it has an associated index and use a model to set the properties:
SideBarElement.qml
import QtQuick 2.0
Item {
property alias icon: sideBarElementicon.source
property bool highlight: false
width: parent.width
Rectangle{
anchors.fill: parent
color: highlight ? Qt.rgba(1,1,0,1) : Qt.rgba(0,0,0,0)
}
Image {
id: sideBarElementicon
source: "genericIcon.png"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 50
height: 50
}
}
SideTabBar.qml
import QtQuick 2.0
import QtQuick.Layouts 1.11
Item {
id: sideTabBar
width: 70
height: parent.height
property int currentIndex: -1
ListModel{
id: elements
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
ListElement {
image: "../assets/product.svg"
}
}
Rectangle{
anchors.fill: parent
color: "purple"
}
ColumnLayout{
id:sidebarLayout
anchors.fill: parent
spacing:2
Repeater{
model: elements
SideBarElement{
id: element
highlight: ix == currentIndex
icon: image
property int ix: index
Layout.preferredHeight: 70
Layout.alignment: Qt.AlignTop
MouseArea{
anchors.fill: parent
onClicked: currentIndex = ix
}
}
}
Item {Layout.fillHeight: true}
}
}

How to access the property of a GridView - or ListView - element

Here is the code, I create 4 buttons. When one is clicked I wanna that its color changes to red and the color of all the others change to black.
But looks like I could not access the color property.
Rectangle {
id: root
width: 200; height: 100
DelegateModel {
id: visualModel
model: ListModel {
ListElement { my_color: "red" }
ListElement { my_color: "black" }
ListElement { my_color: "black" }
ListElement { my_color: "black" }
}
groups: [
DelegateModelGroup { name: "selected" }
]
delegate: Rectangle {
id: item
height: 25
width: 200
color:my_color
MouseArea {
anchors.fill: parent
onClicked: {
console.log(visualModel.items.get(index).color)
for (var i = 0; i < root.count; i++){
if(index == i)
visualModel.items.get(i).color = "red";
else
visualModel.items.get(i).color = "black";
}
}
}
}
}
ListView {
anchors.fill: parent
model: visualModel
}
}
I advice you to use ExclusiveGroup from QML controls. Usually it is used for Action but it's possible to use it for any other Item. From the Qt docs:
It is possible to add support for ExclusiveGroup for an object or
control. It should have a checked property, and either a
checkedChanged, toggled(), or toggled(bool) signal.
So all we need is to add suitable property. Small example:
import QtQuick 2.5
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
Window {
width: 200
height: 400
ExclusiveGroup { id: exclusiveGroup }
ListView {
anchors.fill: parent
anchors.margins: 5
spacing: 2
model: 10
delegate: Rectangle {
id: myItem
property bool checked: false // <-- this is necessary
height: 30
width: parent.width
color: myItem.checked ? "lightblue" : "#DEDEDE"
border { width: 1; color: "#999" }
radius: 5
Text { text: "item" + (index + 1); anchors.centerIn: parent}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: myItem.checked = !myItem.checked;
}
Component.onCompleted: {
exclusiveGroup.bindCheckable(myItem);
}
}
}
}

Resources