I need to move an object by the clock and counterclockwise sequentially. But the for loop works differently, it only moves in the latter direction. When you click on the button, the object must first turn clockwise, and then counterclockwise. Maybe there is some kind of delay when performing the animation? How can I do it?
import QtQuick 2.15
import QtQuick.Window 2.14
import QtQuick3D 1.15
import QtQuick.Controls 2.14
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
visibility: "Maximized"
property int scl: 5
property int angle: 360
Node{
id: standAloneScene
DirectionalLight {
ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0)
}
Node {
id: sphere
Model {
id: model_sphere
source: "#Cube"
x: 200
y: 100
z: 0
materials: [
DefaultMaterial {
diffuseColor: Qt.rgba(0.053, 0.130, 0.219, 0.75)
}
]
}
}
ParallelAnimation{
id: start
running: false
NumberAnimation {
target: sphere
property: "eulerRotation.y"
to: angle
duration: 2000
easing.type: Easing.InOutQuad
}
NumberAnimation {
target: model_sphere
property: "eulerRotation.y"
to: 2*angle
duration: 2000
easing.type: Easing.InOutQuad
}
}
OrthographicCamera {
id: cameraOrthographicFront
eulerRotation.y: 45
eulerRotation.x: -45
x: 600
y: 800
z: 600
}
}
Rectangle {
id: view
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
height: parent.height
color: "#848895"
border.color: "black"
View3D {
id: topLeftView
anchors.fill: parent
importScene: standAloneScene
camera: cameraOrthographicFront
}
Button {
id: posmoveZ
width: view.width/8
height: view.height/16
anchors.top: view.top
anchors.right: view.right
text: "start"
font.pixelSize: height
onClicked: {
for(var i=0; i<6; i++){
if(i % 2 == 0){
angle = 360
}
else{
angle = -360
}
start.restart();
}
}
}
}
}
The simplest answer to your problem is put your animations inside a SequentialAnimation, i.e.
SequentialAnimation {
loops: 3
ParallelAnimation {
id: clockwise
NumberAnimation { /* ... */ }
NumberAnimation { /* ... */ }
}
ParallelAnimation {
id: counterClockwise
NumberAnimation { /* ... */ }
NumberAnimation { /* ... */ }
}
}
Also, you should let QML use the default width and height of a Button. Here's the complete solution:
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import QtQuick3D 1.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
visibility: "Maximized"
property int scl: 5
property int angle: 360
Node{
id: standAloneScene
DirectionalLight {
ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0)
}
Node {
id: sphere
Model {
id: model_sphere
source: "#Cube"
x: 200
y: 100
z: 0
materials: [
DefaultMaterial {
diffuseColor: Qt.rgba(0.053, 0.130, 0.219, 0.75)
}
]
}
}
SequentialAnimation {
id: sequentialAnimation
loops: 3
ParallelAnimation{
id: clockwise
running: false
property int count: 3
NumberAnimation {
target: sphere
property: "eulerRotation.y"
from: 360
to: 0
duration: 2000
easing.type: Easing.InOutQuad
}
NumberAnimation {
target: model_sphere
property: "eulerRotation.y"
from: 720
to: 0
duration: 2000
easing.type: Easing.InOutQuad
}
}
ParallelAnimation{
id: counterClockwise
running: false
NumberAnimation {
target: sphere
property: "eulerRotation.y"
from: 0
to: 360
duration: 2000
easing.type: Easing.InOutQuad
}
NumberAnimation {
target: model_sphere
property: "eulerRotation.y"
from: 0
to: 720
duration: 2000
easing.type: Easing.InOutQuad
}
}
}
OrthographicCamera {
id: cameraOrthographicFront
eulerRotation.y: 45
eulerRotation.x: -45
x: 600
y: 800
z: 600
}
}
Rectangle {
id: view
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
height: parent.height
color: "#848895"
border.color: "black"
View3D {
id: topLeftView
anchors.fill: parent
importScene: standAloneScene
camera: cameraOrthographicFront
}
Button {
id: posmoveZ
anchors.top: view.top
anchors.right: view.right
anchors.margins: 10
text: "start"
font.pixelSize: height
enabled: !clockwise.running && !counterClockwise.running
onClicked: {
sequentialAnimation.restart();
}
}
}
}
Related
With NumberAnimation, I can rotate a 3d object around one of its x, y, or Z axes. I need to rotate the object around the origin - in the picture it is Z.
It's a minimal reproducible example
import QtQuick 2.15
import QtQuick.Window 2.14
import QtQuick3D 1.15
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.12
Window {
id: window
width: 1280
height: 720
visible: true
property int i: 0
property double distance: 1000
Node {
id: standAloneScene
//! [parentnode]
DirectionalLight {
ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0)
}
ParallelAnimation{
id: rotation_y
running: false
NumberAnimation { target: cube; property: "eulerRotation.y"; to: 180*i;
duration: 500; easing.type: Easing.InOutQuad}
}
Model {
id: cube
source: "#Cube"
y: 18
scale: Qt.vector3d(1, 1, 1)
materials: [
DefaultMaterial {
diffuseColor: Qt.rgba(0.228, 0.185, 0.142, 0.5)
}
]
}
OrthographicCamera {
id: cameraPerspectiveIsometry
position: Qt.vector3d(distance, distance*1.5, distance)
eulerRotation.x: -45
eulerRotation.y: 45
}
}
Rectangle {
id: isometry
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
height: parent.height
color: "#848895"
border.color: "black"
Label {
text: "Isometry"
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 10
color: "#222840"
font.pointSize: 14
}
View3D {
id: topLeftView
anchors.fill: parent
importScene: standAloneScene
camera: cameraPerspectiveIsometry
}
}
Button {
anchors.bottom: parent.bottom
anchors.right: right.right
text: "Start"
font.pixelSize: height / 2
onClicked:{
i++;
rotation_y.restart();
}
}
}
I have a QML Map widget. I want to drop some objects on it to get the latitude and longitude of the dropping point. How can I do it?
You can do that exactly as all other drag-n-drop applications. There are tons of examples as in Qt documentation as over the Internet.
One of them:
import QtQuick 2.9
import QtQuick.Window 2.0
import QtLocation 5.3
Window {
id: window
width: 600
height: 400
visible: true
MouseArea {
id: mouseArea
anchors.fill: parent
drag.target: item
propagateComposedEvents: true
onReleased: item.Drag.drop()
}
Plugin {
id: mapPlugin
preferred: ["osm", "esri"]
}
Map {
id: map
anchors.fill: parent
anchors.topMargin: 40
anchors.bottomMargin: 30
plugin: mapPlugin
center {
latitude: 40.785091
longitude: -73.968285
}
zoomLevel: 14
DropArea {
anchors.fill: parent
onDropped: {
var coord = map.toCoordinate(Qt.point(drop.x, drop.y));
output.text = "latitude:" + coord.latitude + ", longitude:" + coord.longitude;
anim.running = true;
}
}
}
Rectangle {
id: item
x: parent.width/2 - 20
y: 0
width: 40
height: 40
radius: 20
color: "orange"
opacity: 1
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 20
Drag.hotSpot.y: 20
Text {
anchors.centerIn: parent
text: "Drop me"
font.pixelSize: 8
}
SequentialAnimation {
id: anim
running: false
NumberAnimation { target: item; property: "opacity"; to: 0; duration: 500 }
PropertyAction { target: item; property: "x"; value: window.width/2 - 20 }
PropertyAction { target: item; property: "y"; value: 0 }
NumberAnimation { target: item; property: "opacity"; to: 1; duration: 500 }
}
}
Text {
id: output
anchors.bottom: parent.bottom
height: 30
width: window.width
text: ""
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
http://doc.qt.io/qt-5/qml-qtquick-controls-styles-sliderstyle.html
Slider {
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
How to access the onReleased and onPressed of the slider in order to start and stop some animation?
Here is what I tried:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
returnAnimation.stop()
}
else
{
console.log("released")
returnAnimation.start()
}
}
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
}
}
Error:
ReferenceError: thumb is not defined
Here is a fully working example. You will have to create your own images referenced here since I can't attach them.
I have found scoping is tricky in QML with component objects. The ":style:handle" component in Slider can "see out" to the higher levels but the higher levels cannot "see in" to the ":style:handle" component.
General Strategy
Create a property in the Top Level Slider scope
Use the property inside the ":style:handle" component since it can "see out"
Use the higher level onPressedChanged handler and the pressed property to adjust the high level property which will be "seen" by the low level component.
Slider {
id: portVoltageSlider
width: 100; height: 27
maximumValue: 150; minimumValue: -150
value: 0.00
stepSize: 10
anchors { centerIn: parent }
// style:handle component will be able to see/access this property
// opacity value of style: SliderStyle:handle.sliderHover
property real hoverOpacity: 0
// adjust property on slider pressed
onPressedChanged: {
// show slider Hover when pressed, hide otherwise
if( pressed ) {
console.log("slider pressed. show hover.")
hoverShowAnimation.start()
}
else {
console.log("slider released. hide hover.")
hoverHideAnimation.start()
}
}
// gratuitous animation using opacity
PropertyAnimation {
id: hoverShowAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 1; duration: 500
}
PropertyAnimation {
id: hoverHideAnimation
target: portVoltageSlider; properties: "hoverOpacity"; from: portVoltageSlider.hoverOpacity; to: 0; duration: 500
}
style: SliderStyle {
id: sliderStyle
property bool hoverVisible: false
groove: Rectangle {
// x: slider1.leftPadding
y: portVoltageSlider.topPadding + portVoltageSlider.availableHeight / 2 - height / 2
implicitWidth: 200; implicitHeight: 4
width: portVoltageSlider.availableWidth; height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
width: portVoltageSlider.visualPosition * parent.width; height: parent.height
color: "yellow"
radius: 2
}
}
handle: Image {
id: sliderHandle
width: 22; height: 24
source: "sliderThumb.svg"
anchors { centerIn: parent }
Image {
id: sliderHover
width: 22; height: 24
source: "sliderValue.svg"
anchors { bottom: sliderHandle.top }
opacity: portVoltageSlider.hoverOpacity
Label {
id: check
anchors {centerIn: parent; verticalCenterOffset: -4 }
text: portVoltageSlider.value
font.pointSize: 6
font.bold: true
}
}
}
}
}
That what I meant in the comment above:
Slider {
...
onPressedChanged: {
if(pressed)
console.log("pressed")
else
console.log("released")
}
}
Would this work?
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 1.4
Window {
visible: true
Slider
{
id: head
property Rectangle thumb: thumb
//Added these signals:
signal startAnim
signal stopAnim
anchors.centerIn: parent
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
id: thumb
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 34
implicitHeight: 34
radius: 12
//Moved animation within the confines of the object that it actually pertains to
ParallelAnimation {
id: returnAnimation
NumberAnimation { target: thumb.anchors; property: "horizontalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
NumberAnimation { target: thumb.anchors; property: "verticalCenterOffset";
to: 0; duration: 200; easing.type: Easing.OutSine }
}
//Signal connections done here:
Component.onCompleted: {
head.startAnim.connect(returnAnimation.start)
head.stopAnim.connect(returnAnimation.stop)
}
}
}
onPressedChanged:
{
if(pressed)
{
console.log("pressed")
startAnim()
}
else
{
console.log("released")
stopAnim()
}
}
}
}
I am trying to make an app which shows 3 pages at a time. The central page shows 3 rectangles displying sql query results 1-3 , the left page is a link to an image from query result 4, and the right page is also built from the same query and has a different layout. Now I am unable to fit these 3 pages into a listmodel and use pathview to make it look like a paginator, because all 3 pages are incongruent and not really a model, hence giving me error ListElement: cannot contain nested elements. I am pasting the code below. All i want is for the user to be able to flick between the pages, whether that involves a pathview or statechange with a decent transition to mimick flipping pages :
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import "content"
Rectangle{
property ListModel mainModel
id: tripleView
visible: true
width: 800
height: 1400
PathView {
model: mainModel
delegate: mainDelegate
id: paginator
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
anchors.fill: parent
path: Path {
startX: -tripleView.width * mainModel.count / 2 + tripleView.width / 2;
startY: tripleView.height / 2
PathLine {
x: tripleView.width * mainModel.count /2 + tripleView.width / 2
y: tripleView.height * .5 }
}
}
Component {
id: mainDelegate
Rectangle {
width: tripleView.width
height: tripleView.height
}
}
ListModel {
id: regionsModel
ListElement {
name: "Stomach"
}
ListElement {
name: "Lung"
}
ListElement {
name: "Colorectal"
}
ListElement {
name: "Pancreas"
}
ListElement {
name: "Urinary Bladder"
}
}
ListModel {
id: mainModel
ListElement{
Rectangle{
id: tnmPage
width: parent.width
height: container.height
Rectangle {
id: menu
z: 2
width: parent.width ;
height: 75
Component {
id: appDelegate
Rectangle {
width: genericText.width + 10; height: parent.height
id: wrapper
color: PathView.isCurrentItem ? "yellow" : "white"
Text {
id: genericText
height: parent.height
font.pointSize: 12
verticalAlignment: Text.AlignVCenter
// anchors.topMargin: wrapper.top
color: wrapper.PathView.isCurrentItem ? "red" : "black"
text: name
}
MouseArea {
// width:parent.width; height: parent.height
anchors.fill: parent
hoverEnabled: true
onClicked: {
var List = mWindow.printi(name)
t.content = List[1]
node.content = List[2]
mets.content = List[3]
view.currentIndex = index
}
}
}
}
PathView {
id: view
width: 2500
height: parent.height
anchors.rightMargin: 18
anchors.bottomMargin: 0
anchors.leftMargin: -18
anchors.topMargin: 0
anchors.fill: parent
// anchors.bottom: parent.bottom
// anchors.top: parent.top
// preferredHighlightBegin: .1
// preferredHighlightEnd: .6
highlightRangeMode: PathView.StrictlyEnforceRange
// anchors.rightMargin: 0
// anchors.bottomMargin: 0
// anchors.leftMargin: 2
// anchors.topMargin: -71
z: 1
highlight: Component {
Rectangle {
color: "yellow"
visible: PathView.onPath
}
}
focus: true
model: regionsModel
delegate: appDelegate
path: Path {
startX: 0; startY: view.height *.5
PathLine { x: menu.width; y: view.height * .5 }
}
}
}
Flickable {
id: flick
anchors.topMargin: menu.bottom
width: parent. width
height: parent. height - menu.height
contentWidth: parent.width+200
contentHeight: container.height // this is calculated on amount of text
PinchArea {
width: Math.max(flick.contentWidth, flick.width)
height: Math.max(flick.height, flick.height)
pinch.minimumScale: 0.5
pinch.maximumScale: 3
property real initialWidth
property real initialHeight
x: 0
y: 0
//![0]
onPinchStarted: {
initialWidth = flick.contentWidth
initialHeight = flick.contentHeight
flick.interactive = false
}
onPinchUpdated: {
t.fontSize = t.size*pinch.scale
node.fontSize = node.size * pinch.scale
mets.fontSize = mets.size * pinch.scale
}
onPinchFinished: {
flick.returnToBounds()
flick.interactive = true
}
Rectangle {
id: container
MouseArea {
anchors.fill: parent
onDoubleClicked: {
t.fontSize = 12
node.fontSize = t.size
mets.fontSize = t.size
}
}
anchors.top: flick.top
width: parent.width
height: t.height + node.height + mets.height
StageBox {
id: t
anchors.top: container.top
color: "#6acbd3"
}
StageBox {
id: node
anchors.top: t.bottom
color: "#1fd77b"
}
StageBox {
id: mets
anchors.top: node.bottom
color: "blue"
}
}
}
}
}
}
I realise the code above is lengthy, but i think it will give some idea about what i am trying to achieve. The examples i have found so far have simple pages displaying images and no nesting. Thank you for your help.
Try QML type VisualItemModel http://qt-project.org/doc/qt-4.8/qml-visualitemmodel.html#details .good luck
I have managed a hack. Experimentally implemented in colored rectangles, this flickable behaves as a 3-page app starting at mid page and allowing flicking horizontally to access neighbouring pages. It works and I am sure with some tweaking it can suit similar applications as mine. Comments invited
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
Rectangle {
state: "baseState"
id: mainScreen
width: 400
height: 600
Text {
z:2
id: logTxt
height: 10
width: 20
function log(txt){
text = txt+"\n"
}
}
Flickable {
boundsBehavior: StopAtBounds
id: flick
y: 48
onContentXChanged: {
if(flick.contentX>100 && mainScreen.state=="baseState" && flick.flickingHorizontally){
logTxt.log(flick.contentX)
mainScreen.state="State1"
}
if(flick.contentX<-100 && mainScreen.state=="baseState" && flick.flickingHorizontally){
mainScreen.state="State2"
logTxt.log(flick.contentX)
}
if(flick.contentX>100 && mainScreen.state=="State2" && flick.flickingHorizontally ){
mainScreen.state="baseState"
logTxt.log(flick.contentX)
flick.contentX=0
}
if(flick.contentX<-100 && mainScreen.state=="State1" && flick.flickingHorizontally){
logTxt.log(flick.contentX)
mainScreen.state="baseState"
flick.contentX=0
logTxt.log(flick.contentX)
Timer
}
}
interactive: true
width: 400
height: 600
transformOrigin: Item.Center
flickableDirection: Flickable.HorizontalFlick
Rectangle {
width: 600
height: 600
id: container
Rectangle {
id:two
visible: false
x: 0
z:3
height: 600
width: 400
color: "grey"
}
Row{
id: testGrid
x:0
visible: true
y: 0
z: 3
width:600
height: 600
Rectangle {
id: a
anchors.top:parent.top
color:"#f6f7b1"
visible: true
z: 3
height: parent.height
width: 200
}
Rectangle {
id: b
anchors.top:parent.top
color:"#ffebeb"
visible: true
height: parent.height
width: 200
}
Rectangle {
id: c
y: -35
anchors.top:parent.top
color:"#b1d5f7"
height: parent.height
width: 200
}
}
Rectangle {
id: three
visible: false
z:2
x:0
height: parent.height
width: 400
color: "#028000"
}
}
}
states: [
State {
name: "State1"
PropertyChanges {
target: testGrid
visible: false
}
PropertyChanges {
target: two
visible: true
}
PropertyChanges {
target: three
visible: false
}
},
State {
name: "State2"
PropertyChanges {
target: testGrid
visible: false
}
PropertyChanges {
target: three
visible: true
}
PropertyChanges {
target: two
visible: false
}
},
State {
name: "baseState"
PropertyChanges {
target: testGrid
visible: true
}
PropertyChanges {
target: three
visible: false
}
PropertyChanges {
target: two
visible: false
}
}
]
}
I wonder how to make smooth transitions betwen image sources in QML, I try
import QtQuick 1.1
Image {
id: rect
source: "quit.png"
smooth: true
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; source :"quit2.png" }
}
transitions: Transition {
NumberAnimation { properties: "scale, source"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
But It does not work on source as a transition just as final state change.. so I wonder how to make one image source fade into andothe and back?
You want the first image to fade out into the other? How about if you place two Image objects on top of each other, then animate the opacity property?
EDIT: This worked for me (I'm using QtQuick 1.0 because my Qt Creator installation is a bit outdated):
import QtQuick 1.0
Rectangle {
Image {
id: rect
source: "quit.png"
smooth: true
opacity: 1
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -10
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: Qt.quit()
}
states: State {
name: "mouse-over"; when: mouseArea.containsMouse
PropertyChanges { target: rect; scale: 0.8; opacity: 0}
PropertyChanges { target: rect2; scale: 0.8; opacity: 1}
}
transitions: Transition {
NumberAnimation { properties: "scale, opacity"; easing.type: Easing.InOutQuad; duration: 1000 }
}
}
Image {
id: rect2
source: "quit2.png"
smooth: true
opacity: 0
anchors.fill: rect
}
}
To the question in your comment: you can place the image exactly on top of the other by copying the anchors thru anchors.fill: rect
Here is also a simple scroll transition between images:
import QtQuick 2.6
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: imageRect
anchors.centerIn: parent
width: 240
height: 320
clip: true
property int currentIndex: 0
property var imageSources: [ "imageLeft.jpg", "imageCenter.jpg" ]
Repeater {
model: imageRect.imageSources
Image {
id: image
width: parent.width
height: parent.height
x: index * parent.width - imageRect.currentIndex * parent.width
fillMode: Image.PreserveAspectFit
source: imageRect.imageSources[index]
Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
}
}
}
Button {
id: leftButton
anchors.bottom: parent.bottom
text: "left"
onClicked: if(imageRect.currentIndex > 0) imageRect.currentIndex--
}
Button {
id: rightButton
anchors.bottom: parent.bottom
anchors.left: leftButton.right
text: "right"
onClicked: if(imageRect.currentIndex < imageRect.imageSources.length - 1) imageRect.currentIndex++
}
Button {
id: addButton
anchors.bottom: parent.bottom
anchors.left: rightButton.right
text: "+"
onClicked: imageRect.imageSources = [ "imageLeft.jpg", "imageCenter.jpg" , "imageRight.jpg" ]
}
}