I was implementing the example, shown at: http://imaginativethinking.ca/how-to-use-qt-quicks-treeview/
I want to add an event handler that reacts, if I click on a tree view item.
The following does not work:
TreeView {
anchors.fill: parent
model: theModel
itemDelegate: Rectangle {
color: ( styleData.row % 2 == 0 ) ? "white" : "lightgrey"
height: 20
Text {
anchors.verticalCenter: parent.verticalCenter
text: styleData.value === undefined ? "" : styleData.value // The branches don't have a description_role so styleData.value will be undefined
}
// console.log("Saving the current project...");
}
TableViewColumn {
role: "name_role"
title: "Name"
width: 110
}
TableViewColumn {
role: "description_role"
title: "Description"
width: 570
}
onCurrentItemChanged: console.log("Running test..")
}
I get the error message:
Cannot assign to non-existent property "onCurrentItemChanged"
Any idea how to add such an event handler?
The following code works:
import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
import ca.imaginativethinking.tutorials.models 1.0
Item {
width: 480
height: 410
MyTreeModel {
id: tests
}
// #disable-check M300
TreeView {
anchors.fill: parent
model: tests
itemDelegate: Rectangle {
color: ( styleData.row % 2 == 0 ) ? "white" : "lightgrey"
height: 20
Text {
anchors.verticalCenter: parent.verticalCenter
text: styleData.value === undefined ? "" : styleData.value // The branches don't have a description_role so styleData.value will be undefined
}
// console.log("Saving the current project...");
}
TableViewColumn {
role: "name_role"
title: "Name"
width: 110
}
TableViewColumn {
role: "description_role"
title: "Description"
width: 570
}
onClicked: {
if (index.parent.row >= 0) {
console.log(index.parent.row, index.row)
console.log(tests.data(index))
}
}
}
}
Instead of using onCurrentItemChanged I use the signal onClicked. I can access the index of the item with index.parent.row and index.row. I can access the content with tests.data(index), where tests is the name of the Model (was named theModel in the question).
I think is better to include a mouse area inside your item delegate, so you can get the onlclick event in each item instead in the whole tree. Something like this:
itemDelegate: MouseArea{
Rectangle {
anchors.fill: parent
color: ( styleData.row % 2 == 0 ) ? "white" : "lightgrey"
height: 20
Text {
anchors.verticalCenter: parent.verticalCenter
text: styleData.value === undefined ? "" : styleData.value // The branches don't have a description_role so styleData.value will be undefined
}
// console.log("Saving the current project...");
}
onClicked: {
console.log(styleData.index)
console.log(tests.data(styleData.index))
}
}
Related
I'm trying to create a Combobox in QML with custom items in it.
Each item must have two Labels/text.
I'm trying to customize it, changing the background etc. but the Items in the popup are rendering outside of its borders
How can I contain the items inside the popup?
This is the closest sample code I could get:
import QtQuick 2.13
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.15
ComboBox {
ListModel {
id: _dataModel
ListElement {
name: "Account1"
numbers: "12345"
}
ListElement {
name: "Account2"
numbers: "12346"
}
ListElement {
name: "Account3"
numbers: "12346"
}
ListElement {
name: "Account4"
numbers: "12346"
}
ListElement {
name: "Account5"
numbers: "12346"
}
ListElement {
name: "Account6"
numbers: "12346"
}
}
id:equipmentList
anchors.verticalCenter: parent.verticalCenter
width: 400
height: 50
model: _dataModel
background: Rectangle {
color: "#95A4A8"
border.color: "white"
}
delegate: ItemDelegate {
id:itemDlgt
width: equipmentList.width
height: 80
contentItem: Column {
id:rectDlgt
width:parent.implicitWidth
spacing: 2
Text {
id: _firstLabel
Layout.preferredHeight: 20
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
color: "black"
font.pixelSize: 16
text: name
}
Text {
Layout.preferredHeight: 16
color: "grey"
font.pixelSize: 14
text: numbers
}
}
}
contentItem: Text {
leftPadding: 20
rightPadding: equipmentList.indicator.width + equipmentList.spacing
text: "This doesnt work either"
font: equipmentList.font
color: "white"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
}
popup: Popup {
id:comboPopup
visible: true
y: equipmentList.height - 50
width: equipmentList.width
height:contentItem.implicitHeigh
padding: 1
contentItem: ListView {
id:listView
implicitHeight: 150
model: equipmentList.popup.visible ? equipmentList.delegateModel : null
ScrollIndicator.vertical: ScrollIndicator {}
}
background: Rectangle {
radius: 7
border.width: 1
}
}
}
I am trying to display a larger version of image inside the GridView when it is clicked, and when I pressed esc button, it will bring me back in the GridView of images, but I can't find a way how to display it in QML, This is my code:
import QtQuick 2.9
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import Qt.labs.folderlistmodel 1.0
import QtQuick.Controls 1.1
import QtQml.Models 2.1
import "qrc:/assets/."
Rectangle {
visible: true
Item {
id: theAboveList
}
GridView {
interactive: false
id: gridView
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
right: parent.right
leftMargin: 5
topMargin: 5
}
cellWidth: width / 2
cellHeight: height / 2
model: folderModel
delegate: fileDelegate
FolderListModel {
id: folderModel
nameFilters: ["*.jpg"]
folder: "file:///E:/QT Projects/ImageViewer/image"
}
Component {
id: fileDelegate
Item {
Image {
width: gridView.cellWidth - 5
height: gridView.cellHeight - 5
smooth: true
source: fileURL
}
}
}
anchors
{
left: parent.left
top: theAboveList.bottom
right: parent.right
bottom: parent.bottom
}
verticalLayoutDirection: GridView.BottomToTop
clip: true
header: Item {}
onContentHeightChanged: {
if (contentHeight < height) {
headerItem.height += (height - contentHeight)
}
currentIndex = count-1
positionViewAtEnd()
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
[ This is where I want to show the clicked image ]
}
}
}
Here is simple illustration of the idea:
Window {
visible: true
width: 400
height: 400
title: qsTr("Images test")
GridLayout
{
width: 303
height: 303
anchors.centerIn: parent
columns: 3
rowSpacing: 1
columnSpacing: 1
Repeater {
model: 9
delegate: Item {
id: container
width: 100
height: 100
z: img.state == "preview" ? 1 : 2
Image {
id: img
cache: false
width: parent.width
height: parent.height
anchors.centerIn: parent
source: "https://picsum.photos/200/200&r=" + Math.random()
fillMode: Image.PreserveAspectFit
MouseArea {
anchors.fill: parent
onClicked: {
img.state = img.state == "preview" ? "full" : "preview";
}
}
state: "preview"
states: [
State {
name: "preview"
PropertyChanges { target: img; width: 100; height: 100; }
},
State {
name: "full"
PropertyChanges { target: img; width: 200; height: 200; }
}
]
transitions: Transition {
PropertyAnimation { properties: "width,height"; duration: 1000; easing.type: Easing.OutBack }
}
}
}
}
}
}
I have a TreeViewand I have an image with a MouseArea in one of the columns. By clicking on it, the focus (selection, highlighting?) doesn't move to the string because the MouseArea is above the TreeView (as far as I understand)
Here is the code:
TreeView
{
clip: true id: mapsTreeView
objectName: "mapsTreeView"
model: theModel
TableViewColumn {
width: 100
role: "name_role"
title: "Map"
}
TableViewColumn {
width: 50
role: "description_role"
}
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
mapsTreeView.sigChangeState()
}
}
Image {
anchors.fill: parent
width: 5
source: "icon" + styleData.value + ".png"
}
}
}
signal sigChangeState()
}
}
The same story applies to the button:
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Button {
iconSource: "icon" + styleData.value + ".png"
onClicked: mapsTreeView.sigChangeState()
}
}
When I click on the button, the focus doesn't moves to the string that contains button.
So the question is, how to make the image/button delegate so that by clicking on it focus will move to the string that contains this object, and some signal is emitted.
In ListView, all I had to do was simply the following:
onClicked:{
mapsView.currentIndex=model.index
mapsState.sigChangeState()
}
But TreeView doesn't allow one to write CurrentIndex
I would like to add a MouseArea/Button to a TableViewColumn to perform specific tasks. However, if I add one of the above type, it overrides the "click" event of TableViewColumn so that I lose row selection.
Here is an example code. The row is not switching when I click it in the area of the last column:
TreeView {
clip: true id: mapsTreeView
objectName: "mapsTreeView"
model: theModel
TableViewColumn {
width: 100
role: "name_role"
title: "Map"
}
TableViewColumn {
width: 50
role: "description_role"
}
TableViewColumn {
id: imageColumn
width: 20
role: "image_role"
delegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
mapsTreeView.sigChangeState()
}
}
Image {
anchors.fill: parent
width: 5
source: "icon" + styleData.value + ".png"
}
}
}
signal sigChangeState()
}
Maybe there is a better solution, but this works for me:
MouseArea {
anchors.fill: parent
onContainsPressChanged: {
if(containsPress)
{
console.log("PRESSED")
}
}
onPressed: {
mouse.accepted = false
}
}
I'm trying to get data from a specific column when the row is selected.
For exemple, when the user selects the first row, I need to retrieve the value of the column "Image source". Many thanks!!
main.qml
TableView {
onClicked: {
console.log("value "+ column2.value )
}
id:tablev
model: mySQLmodel
anchors.margins: 12
anchors.fill: parent
TableViewColumn {
id: column1
role: "Title"
title: "Title"
width: 120
}
TableViewColumn {
id: column2
role: "Credit"
title: "Credit"
width: 120
}
TableViewColumn {
id: column14
role: "Image"
title: "Image source"
width: 120
}
itemDelegate: Text
{
text: styleData.value
elide: Text.ElideRight
} }}}
Assume you are using TableView with model.
ListModel {
id: libraryModel
ListElement{ title: "A title 1" ; credit: "N/A"; source: "http://someurl.com" }
ListElement{ title: "A title 2" ; credit: "N/A"; source: "http://someurl.com" }
ListElement{ title: "A title 3" ; credit: "N/A"; source: "http://someurl.com" }
}
TableView {
TableViewColumn{ role: "title" ; title: "Title" ; width: 100 }
TableViewColumn{ role: "credit" ; title: "Credit" ; width: 200 }
TableViewColumn{ role: "source" ; title: "Image source" ; width: 200 }
model: libraryModel
}
So you can add onClick event to the view in that way:
onClicked: {
console.log(libraryModel.get(row).source);
}
when row is the selected row passed to onClicked by engine
[Solved]
I use the function bellow and works great:
QVariantMap Model::get(int idx) const {
QVariantMap map;
foreach(int k, roleNames().keys()) {
map[roleNames().value(k)] = data(index(idx, 0), k);
}
return map;
}
Happy codding :)
You could add something like:
`
TableView {
itemDelegate: Item {
MouseArea {
anchors.fill: parent
onClicked: {
console.log("row: " + styleData.row + " column: " + styleData.column + " value: " + styleData.value)
}
}
}
}
`