QML how to get index number in a ListView by clicking a checkbox defined inside a delegate of a listView? - qqmlcomponent

Well I am trying to make a list of items having two texts and a checkbox in a listView.
I wanted to add the price of the item when the checkbox is checked.
To accomplish this, I need to know the index of the item of a listView so that I could get
its "price" and I could store the data.
I am unable to get the current Index of a list through a checkbox, as it behaves as
an individual entity.
However, I could get the index if I put a mouse area, but I need to grab it by checkbox.
for reference:
Component { // delegate
id:_delegate
Rectangle{
width: 100
height: 50
color: "beige"
border.color: "black"
Text {
id: _textid
text: name
}
Text {
id: _textid2
anchors.top: _textid.bottom;anchors.topMargin: 5
anchors.left: _textid.left
text: price
}
CheckBox {
id:_checkbox
anchors.top:parent.top;anchors.topMargin: 5
anchors.left: parent.left;anchors.leftMargin: 50
}
}

You can use the onCheckedChanged event and then get the price of the current index from your model, like this:
Component { // delegate
id:_delegate
Rectangle{
width: 100
height: 50
color: "beige"
border.color: "black"
Text {
id: _textid
text: name
}
Text {
id: _textid2
anchors.top: _textid.bottom;anchors.topMargin: 5
anchors.left: _textid.left
text: price
}
CheckBox {
id:_checkbox
anchors.top:parent.top;anchors.topMargin: 5
anchors.left: parent.left;anchors.leftMargin: 50
onCheckedChanged: {
_textid2.text = _checkbox.checked ? your_model.get(index).price : ""
}
}
}

Related

Can labels be hidden by default, but shown when the node is selected?

I want my graph has no label by default, but when I select a node its label will show up. There is chosen.label that seems promising, but I still don't know how to write the function. There is also a question about scaling.label, but as indicated in there it also seems not working.
Another approach is to have a checkbox to turn on and off the labels. See: Can the filter in the configure option specify an only option?
This can be achieved using the chosen.label option in combination with the transparent font color.
In the options object firstly set the default font color for nodes to transparent, then within chosen.label adjust it to a visible color.
var options = {
nodes: {
font: {
// Set default label font color to transparent
color: "transparent"
},
chosen: {
label: function(values, id, selected, hovering) {
// Adjust label font color so it is visible
// Updates to the values object are applied to the network
values.color = "#343434";
}
}
}
};
Working example is below.
// create an array with nodes
var nodes = new vis.DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" }
]);
// create an array with edges
var edges = new vis.DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 3, to: 3 },
]);
// create a network
var container = document.getElementById("mynetwork");
var treeData = {
nodes: nodes,
edges: edges,
};
var options = {
nodes: {
font: {
// Set default label font color to transparent
color: "transparent"
},
chosen: {
label: function(values, id, selected, hovering) {
// Adjust label font color so it is visible
// Updates to the values object are applied to the network
values.color = "#343434";
}
}
}
};
var network = new vis.Network(container, treeData, options);
#mynetwork {
width: 600px;
height: 180px;
border: 1px solid lightgray;
}
<script src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
<div id="mynetwork"></div>

Change height of column for animation

I have created a simple tree which I wish to animate by having branches height expand/collapse visually. My code below works by switching only the visible attribute, so that if I click on the branch it can appear/disappear.
However I want to animate the height of the column from normal to 0 and back. The problem is, the height of the column never changes when the state changes. Why?
import QtQuick 2.0
import QtQuick.Layouts 1.12
Column {
id: menuGroup
property string path: "/"
property bool _onCurrentPath: (treeMenu._currentPath.indexOf(path) === 0)
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
// visible: _onCurrentPath <-- this works
states: [
State {
name: "HIDDEN"
when: !_onCurrentPath
PropertyChanges { target: menuGroup; height: 0}
},
State {
name: "VISIBLE"
when: _onCurrentPath
PropertyChanges { target: menuGroup; height: 600 } //menuGroup.implicitHeight}
}
]
transitions: Transition {
PropertyAnimation { property: "height"; duration: 500; easing.type: Easing.InOutQuad }
}
onStateChanged: {
console.log("Group "+path+" state "+state)
}
}
Is it not possible to force the height of a column? (Do I have to wrap it in a Rectangle or some other solution)?
The first thing I noticed when running your code was that onStateChanged was not executing. It seems that your when: _onCurrentPath is not evaluating due to a scoping problem that does not trigger an error or warning. I changed this to when: menuGroup._onCurrentPath in both cases and I was able to start seeing the state changes.
Secondarily, I had to enable clip: true to make sure that the contents of the column were actually trimmed, otherwise it visually didn't make a difference that the column was collapsing, as the contents stayed visible.
Here is a full working example (modified your _onCurrentPath bool to simplify testing):
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
Window {
width: 640
height: 480
visible: true
Column {
id: menuGroup
property string path: "/"
property bool _onCurrentPath: button.checked
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
clip: true // Must enable to actually clip contents of column when collapsing
states: [
State {
name: "HIDDEN"
when: !menuGroup._onCurrentPath // Must explicitly state menuGroup here
PropertyChanges { target: menuGroup; height: 0}
},
State {
name: "VISIBLE"
when: menuGroup._onCurrentPath
PropertyChanges { target: menuGroup; height: 600 }
}
]
transitions: Transition {
PropertyAnimation { property: "height"; duration: 500; easing.type: Easing.InOutQuad }
}
onStateChanged: {
console.log("Group "+path+" state "+state)
}
Rectangle { // Some column content for demonstration
color: "red"
implicitHeight: 600
implicitWidth: 200
}
}
Button {
id: button
anchors.bottom: parent.bottom
checkable: true
text: "Change States"
}
}

GridView delegates transitions do not work

I have following QML GridView:
GridView
{
id: ueProductGridView
antialiasing: true
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
cellWidth: 200
cellHeight: 200
delegate: Rectangle
{
id: test
width: 192
height: 192
color: "red"
Text
{
anchors.fill: parent
text: index
}
transform:
[
Rotation
{
id: plateRotation
angle: -90
axis { x: 0; y: 1; z: 0 }
origin.x: -200
origin.y: 0
}
] // transform
SequentialAnimation
{
id: addAnimation
PauseAnimation
{
duration: Math.random()*2000
}
NumberAnimation
{
target: plateRotation
property: "angle"
to: 0
duration: 1000
}
}
SequentialAnimation
{
id: removeAnimation
PropertyAction
{
target: test
property: "GridView.delayRemove"
value: true
}
NumberAnimation
{
target: test
property: "scale"
to: 0
duration: 1000
}
PropertyAction
{
target: test
property: "GridView.delayRemove"
value: false
}
}
GridView.onAdd:
{
addAnimation.start();
} // onAdd
GridView.onRemove:
{
removeAnimation.start();
} // onRemove
} // delegate
Component.onCompleted:
{
model=10;
} // onCompleted:
} // GridView
Now, why delegate animations do not work, i.e., why GridView is empty? The code regarding animations was taken from tutorial and in there it works. However, if I comment/remove all code regarding animations, delegates are visible in GridView and it is all ok:
GridView
{
id: ueProductGridView
antialiasing: true
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
cellWidth: 200
cellHeight: 200
delegate: Rectangle
{
id: test
width: 192
height: 192
color: "red"
Text
{
anchors.fill: parent
text: index
}
} // delegate
Component.onCompleted:
{
model=10;
} // onCompleted:
} // GridView
The animations associated to insertion/removal of elements from the views are Transitions (e.g. see add), between different States and are indeed called ViewTransitions. You should really take a deep look at the documentation page of this type: it is full of nice examples and describes in great details how addition/removal animations should be implemented.
When you define a ViewTransition, any property referenced inside it, if not differently targeted, refer a delegate property. Hence, if you write inside your GridView:
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 500 }
NumberAnimation { property: "scale"; easing.type: Easing.OutBounce; from: 0; to: 1.0; duration: 750 }
}
you are saying that each time a new delegate is added to the grid, its opacity as well as scale properties should be animated. Top level animations, like in this case, run in parallel so the delegate is scaled and made visible at the same time.
Now, if you want to animate nested properties, like in the case of the Rotation angle, the easiest way is to alias it inside the delegate. That way it can be handled exactly the same way as any other delegate property, resulting in a clearer and simpler code.
It should be noted that the animations in your example does not work also because they are associated to add Transition. Such Transition is not used during model initialisation when instead the populate Transition is used. From the documentation:
This property holds the transition to apply to the items that are initially created for a view.
It is applied to all items that are created when:
The view is first created
The view's model changes
The view's model is reset, if the model is a QAbstractItemModel subclass
Finally, an advice. If you animate addition and removal of elements, especially if the animation is slow, it is also important to animation the adjustment made by the view to the other elements. Animating them in a graceful way can improve visual feeling A LOT. Hence, when you provide a add and a remove transition, take in account also the addition of a addDisplaced and a removeDisplaced Transition.
Here follows a modified version of your code that shows all the points discussed above:
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
id: window
width: 600
height: 400
visible: true
ListModel {
id: model
ListElement { code: "0" }
ListElement { code: "1" }
ListElement { code: "2" }
ListElement { code: "3" }
ListElement { code: "4" }
ListElement { code: "5" }
}
GridView {
id: ueProductGridView
anchors.fill: parent
antialiasing: true
clip: true
cellWidth: 200
cellHeight: 200
delegate: Rectangle {
width: 192
height: 192
color: "red"
property alias angle: rot.angle // alias!
Text {
anchors.centerIn: parent
text: code
font.pixelSize: 30
}
transform: Rotation {
id: rot
angle: -90
axis { x: 0; y: 1; z: 0 }
origin.x: -200
origin.y: 0
}
MouseArea {
anchors.fill: parent
onClicked: ueProductGridView.model.remove(index)
}
} // delegate
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 500 } //since is already at 1.0 we should enforce the start from 0
NumberAnimation { property: "scale"; easing.type: Easing.OutBounce; from: 0; to: 1.0; duration: 750 }
}
addDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 200; easing.type: Easing.InBack }
}
remove: Transition {
NumberAnimation { property: "scale"; from: 1.0; to: 0; duration: 200 }
}
removeDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 200; easing.type: Easing.OutBack }
}
populate: Transition {
NumberAnimation { properties: "angle"; to: 0; duration: 500 }
}
}
Component.onCompleted:{ ueProductGridView.model= model }
}

How to set a image source outside Component

I have a image showing up in a Dialog in my QML app, and I want to be able to change that image later on using onClicked, which I pass by a function to check if the variable I want in the new source URL is one of them I want.
I've tried just by using Image.source = "NEWURL" which is a no go. Also the id of the component the image is in, and the dialog like: id.source = "neurl" - no go.
How do I do that?
EDIT: Added more code; both the function and then listitm used to click. The image is a web image, and I want to have the conncectedUser value (which is a user name) inside the url.
Here is all the related code:
// Check if users is really a user, and if; show skin
function checkCurrentUser(currentUser) {
console.debug('Debug: Check user "'+currentUser+'" if actually a user.')
if (currentUser == "Ingen online") {
currentUser = "Notch" // reset currentUser if pushed earlier
console.debug('Debug: It was not a real user. Showing '+currentUser+' instead')
Image.source = "http://blabla"+currentUser+"yesyes"
}
else {
console.debug('Debug: It was a real user.')
Image.source = "http://blabla"+currentUser+"yesyes"
}
return "http://blabla"+currentUser+"yesyes""
}
// the dialog I want to show with a image
Component {
id: userDialog
Dialog {
id: dialogueUser
title: i18n.tr("Image")
Image {
id: usersSkin
fillMode: Image.PreserveAspectFit
source: "URL"
sourceSize.height: 1200
}
Button {
text: i18n.tr("Close")
color: "red"
onClicked: PopupUtils.close(dialogueUser)
}
}
}
// and then the list containting each link, which on click should show the user image
ListView {
id: userList
width: parent.width
height: units.gu(5)
model: msmData
delegate: ListItem.Standard {
text: connectedUser
onClicked: {
console.debug('Debug: User clicked "'+connectedUser+'"')
checkCurrentUser(connectedUser)
PopupUtils.open(userDialog, userList)
}
}
header: ListItem.Header { text: i18n.tr("Connected Users") }
section.property: "type"
section.criteria: ViewSection.FullString
section.delegate: ListItem.Header { text: i18n.tr(section) }
}
I am not sure if I understood your question correctly, but I will give it a try:
Component
{
id: userDialog
Dialog
{
property int sourceState : 1
id: dialogueUser
title: i18n.tr("Image")
Image
{
id: usersSkin
fillMode: Image.PreserveAspectFit
source: 1 == sourceState ? "OLDURL" : "NEWURL"
sourceSize.height: 1200
}
Button
{
text: i18n.tr("Close")
color: "red"
onClicked:
{
PopupUtils.close(dialogueUser)
dialogueUser.sourceState = 0
}
}
}
}
What I finally did was to just reset the variable in the image URL, and then show the dialog. Working now.

UI issue in Progress Bar animation

I'm developing a progress bar in QML.
But the working is not working for all parameter values.
Its more bit of logical issue in UI
Requesting everyone to review it.
below is the code snippet
Rectangle
{
width: 500; height: 480
.....
color: "lightyellow"
Rectangle {
id: container
....
Row {
id:repeaterid
Repeater {
id: repeater
model: 100
Item { id: smallrect2; opacity:0.5; width:_width; height:_height
Rectangle { id: smallrect; color: _newColor }
......
}
}
}
Timer {
id: progressTimer
interval: 100
onTriggered: {
if ((slider.x + slider.width) < repeaterid.width)
{
slider.x += _width
var item = repeater.itemAt(indexCurrent)
item._newColor = "red"
indexCurrent++
}
else
{
progressTimer.repeat = false
}
}
}
Rectangle {
id: slider
// Adjust the dimensions of slider
x: repeaterid.x
y: repeaterid.y
width: _width
height: _height
}
}
}
The desired behaviour is achieved when value of _width is 30 and the model value in the repeater is 18, but as the value is decreased the slider in progress bar doesn't complete its path ( width = 5, model =100 ) or if increased it moves out of the path.
Solved : Adjusted model value according to container size & rectangle size

Resources