Unsolved Animation between images
-
Hello,
I have a little qml that show an image based on some events from c++ backend. I created some states and for each state I have have set the properties for every single image to obtain the effect I want.
But my qml code looks ugly. I want simple as active image slide to left while at the same time next image to show slide from right side (800px) to left (0px)
I have read QML Repeater but it doesn't accept an array of image objects.
How would you do that? I have tried also to set the target an image object but it doesn't seem to work.
Can you point me some steps?
Thank you
import QtQuick 2.4 import QtQuick.Window 2.2 Window { visible: true width: 800; height: 480 Rectangle { id: page state: msg.author width: 800; height: 480 color: "#FEDC32" Text { id: tutorial z: 100 width: 100; height: 100 text: msg.author // invokes Message::author() to get this value Component.onCompleted: { msg.author = "Jonah" // invokes Message::setAuthor() } function teste(){ msg.author = "teste2" } } Text { id: tutorial2 z: 100 y: 50 width: 100; height: 100 text: msg.debug // invokes Message::author() to get this value } states: [ // This adds a second state to the container where the rectangle is farther to the right State { name: "quarto" PropertyChanges { target: quartoImage x: 0 } PropertyChanges { target: mainImage x: -800 } PropertyChanges { target: salaImage x: -800 } PropertyChanges { target: escImage x: -800 } }, State { name: "sala" PropertyChanges { target: salaImage x: 0 } PropertyChanges { target: quartoImage x: 800 } PropertyChanges { target: mainImage x: 800 } PropertyChanges { target: escImage x: -800 } }, State { name: "main" PropertyChanges { target: quartoImage x: 800 } PropertyChanges { target: salaImage x: -800 } PropertyChanges { target: mainImage x: 0 } PropertyChanges { target: escImage x: -800 } }, State { name: "esc" PropertyChanges { target: quartoImage x: 800 } PropertyChanges { target: salaImage x: -800 } PropertyChanges { target: mainImage x: 800 } PropertyChanges { target: escImage x: 0 } } ] transitions: [ Transition { from: "main"; to: "quarto";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } }, Transition { from: "quarto"; to: "main";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } }, Transition { from: "main"; to: "sala";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } }, Transition { from: "sala"; to: "main";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } }, Transition { from: "main"; to: "esc";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } }, Transition { from: "esc"; to: "main";// reversible: true ParallelAnimation { NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad } ColorAnimation { duration: 500 } } } ] MouseArea { x: 0 y: 0 width: 399; height: 480; onClicked: { console.log(page.state+"->"); page.state = "sala"; console.log(page.state) } } MouseArea { x: 401 y: 0 width: 399; height: 480; onClicked: { console.log(page.state+"->"); page.state = "quarto"; console.log(page.state) } } Image { id: mainImage source: "qrc:/ikea.jpg" anchors.verticalCenter: page.verticalCenter } Image { id: salaImage source: "qrc:/sala.jpg" anchors.verticalCenter: page.verticalCenter MouseArea { anchors.fill: parent; onClicked: { console.log();console.log(page.state+"->"); page.state = "main"; console.log(page.state) } } } Image { id: quartoImage source: "qrc:/quarto.jpg" MouseArea { anchors.fill: parent; onClicked: { console.log(page.state+"->"); page.state = "main"; console.log(page.state) } } } Image { id: escImage source: "qrc:/esc.jpg" MouseArea { anchors.fill: parent; onClicked: { console.log(page.state+"->"); page.state = "main"; console.log(page.state) } } } } }
-
Use ListView to show a list of images.
import QtQuick 2.4 Item { id: root ListView { anchors.fill: parent orientation: ListView.Horizontal // content will move horizontally when scrolling snapMode: ListView.SnapOneItem // scrolling won't stop at the middle of an image interactive: false // is not scrollable with mouse or keyboard arrows delegate: Item { width: root.width // if the image is smaller than the window, the next image will be still out of the screen Image { source: modelData } } model: [ "1.jpeg", "2.jpeg", "3.jpeg", "4.jpeg", "5.jpeg" ] MouseArea { anchors.fill: parent onClicked: parent.currentIndex += 1 // scroll to next when clicked } } }
-
@devel Thank you for the example :)
However I want to be able to change from 1.jpg to 3.jpg per example. So all the images that aren't on center should be ready to show. -
A bit hacky solution with Path. I'm not sure that PathView guarantees exact positioning of the elements. Maybe it's time to go back to the PropertyAnimations that you were doing before.
import QtQuick 2.4 Item { id: root PathView { anchors.fill: parent interactive: false model: 2 // will hold 2 empty images delegate: Item { width: root.width property alias source: img.source Image { id: img } } path: Path { startX: root.width * 1.5 // starting point is the middle of the imaginary screen on the right (center of the next Item is here) startY: 0 PathLine { x: -root.width * 0.5; y: 0 } // destination point is the middle of the imaginary screen on the left (center of the current item will slide to here) } MouseArea { anchors.fill: parent onClicked: { parent.currentIndex += 1 parent.currentItem.source = "4.jpeg" } } } }
Also, to see what's really going on, I've added some coloured rectangles. Launch the next code with
QSG_VISUALIZE=overdraw
environment variable to see the stuff that's outside the window.Command line:
$ QSG_VISUALIZE=overdraw qmlscene path.qml
Code (almost the same):
import QtQuick 2.4 Item { id: root PathView { anchors.fill: parent interactive: false model: 2 // will hold 2 empty images delegate: Rectangle { height: 50 color: ["red","blue"][modelData] width: root.width property alias source: img.source Image { id: img } } path: Path { startX: root.width * 1.5 // starting point is the middle of the imaginary screen on the right (center of the next Item is here) startY: 0 PathLine { x: -root.width * 0.5; y: 0 } // destination point is the middle of the imaginary screen on the left (center of the current item eill slide to here) } MouseArea { anchors.fill: parent onClicked: { parent.currentIndex += 1 parent.currentItem.source = "4.jpeg" } } } }
-
@devel I understand the idea. Now I'm trying to set the next image from C++. I was looking on how to change the model from c++ ( http://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html ) but after the PathView is created any changes on the model from C++ doesn't take any action on QML :s
-
The model-view is when we give all images to ListView/PathView (or something like that) and then let user to manipulate them.
The last example with PathView isn't a real model-view. It's a hack to show just one image and to be able to change it with a sliding effect.
It's possible to control the image via a property like that for example:
import QtQuick 2.4 Item { id: root property url imageSource onImageSourceChanged: { pathView.currentIndex += 1 pathView.currentItem.source = imageSource } PathView { id: pathView anchors.fill: parent ...
C++ can definitively bind something different to this new imageSource property.