Stackview replace qml after button animation is completed - qt

i am building an interface with QtQuick2 by using qmls. I also created a few buttons on home page and i am trying to change qmls by using loader after some animation is played. I have a stackview like this:
StackView {
id: stackViewTool
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: bottomBar.top
}
initialItem: initializePage
}
and i also added "initializePage" variable as property
property string initializePage : "HomePage.qml"
here is how i use my button to change qml on some other pages.
SimpleButton {
id:homeClicked
Image{
id: homeID
source:"/images/barHome.png"
}
onClicked: {
stackViewTool.replace(initializePage)
}
}
I want to add a animation to get the "pushing button" feeling. I want to change the button image first, and then i want to replace the qml. Here is the sequental animation i want to use. I want to have the animation like pushed and released, then change the qml.
SequentialAnimation {
id : homePressed
PropertyAnimation {
targets: [homeID]
property: "source"
to: "/images/pressedHome.png"
}
PauseAnimation {
duration: 100
}
PropertyAnimation {
targets: [homeID]
property: "source"
to: "/images/barHome.png"
}
PauseAnimation {
duration: 100
}
}
I tried to use "stackViewTool.replace(initializePage)" after the sequential animation but it did not work. I tried to add "Component.onCompleted: stackViewTool.replace(initializePage)" after 100ms pause snippet(last step of animation) but it did not work. What can i do for create something like i wanted? Answers are appreciated.

You can use the onFinished | onStarted signal handlers.
You can use ScriptAction at the end of the animation:
SequentialAnimation
{
id: homePressed
PropertyAnimation {
targets: [homeID]
property: "source"
to: "/images/pressedHome.png"
}
PauseAnimation {
duration: 100
}
PropertyAnimation {
targets: [homeID]
property: "source"
to: "/images/barHome.png"
}
PauseAnimation {
duration: 100
}
ScriptAction{
script: function(){stackViewTool.replace(initializePage)}
}
}

Related

QML: How to move an object from a previous set postion using states

I have an object that I want to move from it's previously set position every time that particular state is set. I've tried making a separate property called xPos to get around the binding loop error which is set by the object's new position of x after the state is set, then entering a default state just to be able to switch back to that specific state again since calling the same state does nothing but it doesn't seem to work.
Here is a snippet of my code:
property int xPos: 0
states: [
State {
name: "nextStep"
PropertyChanges {
target: progressBar_Id
x: -1*(progressBar_Id.step.width) + xPos
}
},
State {
name: "previousStep"
PropertyChanges {
target: progressBar_Id
x: progressBar_Id.step.width + xPos
}
},
State {
name: "default"
PropertyChanges {
target: progressBar_Id
x: xPos
}
}
]
transitions: [
Transition {
from: "*"
to: "nextStep"
NumberAnimation {properties: "x"; easing.type: Easing.Linear; duration: 1000}
onRunningChanged: {
if(!running) {
xPos = progressBar_Id.x;
console.info("xPos = " + xPos);
state = "default";
}
}
},
Transition {
from: "*"
to: "previousStep"
NumberAnimation {properties: "x"; easing.type: Easing.Linear; duration: 1000}
onRunningChanged: {
if(!running) {
xPos = progressBar_Id.x;
console.info("xPos = " + xPos);
state = "default";
}
}
}
]
xPos seems to get set the first time from the console output but never applies the new xCoord to the object.
Explicitly specify the id of the item on which you wish to set the state, e.g:
idOfComponent.state = "default"
All QML Items and derivatives have a property called state, so the code needs to be more specific.
Actually came up with a much better alternative using a ListView.
ListView {
id: listView_Id
width: contentWidth
height: bubbleSize
anchors.centerIn: parent
layoutDirection: Qt.RightToLeft
orientation: ListView.Horizontal
spacing: 0
delegate: Item {
width: bubbleSize
height: width
ProgressBubble {
stateText: stateNumber
currentState: state
}
}
model: ListModel { id: progressModel_Id }
}
Another qml file:
progressModel.insert(0, {stateNumber: number++, state: "current"});
But I ran into another problem, is there anyway to change a state within a delegate after it's been added to the ListView?
I've already tried progressModel.set and progressModel.setProperty but doesn't seem to work.
state is a property for qml types, so when you are assigning "state" to "currentState" for "ProgressBubble", its taking the value of state in which " ProgressBubble" is currently present.
Rename "state" to something else like "presentState" and then try.
Moreover id of ListView model(progressModel_Id) and the one used to insert model elements(progressModel) in different file are different, both of them must refer to same id.
After these changes, you can try set property of model. Sample code snippet:
import QtQuick 2.0
Rectangle {
id: root
width: 360
height: 360
property int number: 1
ListView {
id: listView_Id
width: 100 //contentWidth // this creates property binding issue
height: 100 // bubbleSize // I was not sure about this value
anchors.centerIn: parent
layoutDirection: Qt.RightToLeft
orientation: ListView.Horizontal
spacing: 0
delegate: Item {
width: 100 // bubbleSize // I was not sure about this value
height: width
ProgressBubble {
state: "default"
stateText: stateNumber
currentState: presentState
MouseArea {
anchors.fill: parent
onClicked: {
progressModel_Id.set(index,{stateNumber: stateNumber, presentState: "not current"})
}
}
}
}
model: ListModel { id: progressModel_Id }
}
Component.onCompleted:
{
progressModel_Id.insert(0, {stateNumber: number++, presentState: "current"});
}
}

does qtquick have a function such as wait()?

Is there something like a wait() function for qtquick? I have as mousearea that calls an animation and a different state. When you click the mousearea they are both fired at the same time I need the state change to fire after the animation is completed.
MouseArea {
id: movie_mouse_mm
x: 392
y: 364
width: 104
height: 100
onClicked:{
image6.state = "rotated"
page.state = 'State1'
Logic.get_db(5,0);
}
}
So I need to get
page.state ='state'
to run after
image6.state= "rotated"
You have to use transitions & animations like that:
Item {
//...
MouseArea {
//...
onClicked:{
parent.state = "rotate"
//...
}
}
transitions: [
Transition {
to: "rotate"
SequentialAnimation {
RotationAnimation { target: image6; duration: 1000; direction: RotationAnimation.Clockwise }
PropertyAction { target: page; property: "state"; value: "state" }
}
}
]
}
You can adjust duration
More information here.

using loader in qml

I have multiple QML files. I just want to link them. Then I want to return to my home page from every page I navigate to. I am using loader in every page
Here is my code.
import QtQuick 1.1
Rectangle{
id:welcome
width:480
height:272
Loader{
id:loader
focus:false
anchors.fill: parent
}
gradient: Gradient {
GradientStop { position: 0.0; color: "light blue" }
GradientStop { position: 1.0; color: "blue" }
}
Text{
text:"\n\t\tPRESS ENTER"
font.bold:true
font.pointSize: 17
}
Button {
id: wel
height:30;
x:parent.width/2-30
y:parent.height/2-30
focus:true
border.color:"black"
opacity: activeFocus ? 1.0 : 0.5
Text{
text:"WELCOME"
anchors.horizontalCenter:wel.horizontalCenter;
anchors.verticalCenter:wel.verticalCenter;
}
Keys.onReturnPressed: {
wel.focus=false
loader.focus=true;
anchors.fill=parent
loader.source="Home.qml";
//welcome.visible=false;
}
}
}
My question is whenever I click on the button its loading new file. But the welcome page will not go. Both the file's will be overlapped. When I did visible=false complete UI will go. I get a white screen.
Can any one help me fix this problem?
How to load other file?
To load multiple pages you will need to use Connections element to handle signal from the page you have loaded.
Loader {
id: windowLoader
source: "Welcome.qml"
focus: true
property bool valid: item !== null
}
Button {
Keys.onReturnPressed: {
windowLoader.source = "Page1.qml"
}
}
Connections {
ignoreUnknownSignals: true
target: windowLoader.valid? windowLoader.item : null
onChangeToPage2: { windowLoader.source = "Page2.qml" }
onPageExit: { windowLoader.source = "Welcome.qml" }
}
And from the pages you load you will need to emit the "changeToPage2" and "pageExit" signals. The emitted signals will be handled by the Connections element.
Page1.qml:
Rectangle {
id: page1
signal changeToPage2
signal pageExit
Button {
id: exitButton
Keys.onReturnPressed: { page1.pageExit() }
}
}

QML zoom from a clicked rectangle to another UI element

I have 9:9 matrix of Rectangle elements on the main QML form with Repeater. What I want to implement is if user clicks on one of rectangles, it zooms to TextEdit widget which on Esc press zooms back.
Is it possible with QML?
If yes, how am I supposed to turn Rectangle to TextEdit and zoom this TextEdit to fill the parent?
Just starting to work with QML and can't quite get an answer from http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeanimation.html yet.
Thank you.
1) Sure thing! This is more or less what QML is made for.
2) This is an example of how you can do what you want (not the only way to do it):
Rectangle {
id: parentRect
width: 500; height: 500
// Every item in the grid should look like this
Rectangle {
id: singleItem
color: "red"
state: "closed"
// Hidden text input, shown when user clicks
TextInput {
id: textInput
anchors.fill: parent
text: "Input here"
cursorVisible: true
}
// MouseArea that will catch the user click
MouseArea {
anchors.fill: parent
onClicked: singleItem.state = "open"
}
// Item states
states: [
State {
name: "closed"
PropertyChanges {target: singleItem; width: 25; height: 25}
PropertyChanges {target: textInput; opacity: 0}
},
State {
name: "open"
PropertyChanges {target: singleItem; width: parentRect.width; height: parentRect.height}
PropertyChanges {target: textInput; opacity: 1; focus: true}
}
]
// Transitions between states
transitions: Transition {
ParallelAnimation {
NumberAnimation {
target: singleItem
properties: "width,height"
duration: 1000
}
NumberAnimation {
target: textInput
property: "opacity"
duration: 1000
}
}
}
}
}
Even I'm new to qt-quick. I don't think it is possible to zoom unless we write our code to do such. I'm not sure though. :-)
This effect is good and it will b nice to see in coming versions. Try to give a feature request to the community <3

Playing a QML animation more than once without using States

I'm trying to get an QML animation to Start every time it's clicked, without using States. It Starts the first time it's clicked, but then won't Start when it's clicked a second time.
Is there a reason why? Here's the code I'm working it.
Image {
id: head;
source: "vlad.png";
height: 80;
width: 90;
MouseArea {
anchors.fill: parent
onClicked: animateHead.start();
ParallelAnimation {
id: animateHead;
NumberAnimation {
property int randomValueX: 0;
function randomize(randomValueX) {
randomValueX = (Math.floor(Math.random()*210));
return randomValueX;
}
target: head;
properties: "x";
to: randomize(randomValueX);
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
NumberAnimation {
property int randomValueY: 0;
function randomize(randomValueY) {
randomValueY = (Math.floor(Math.random()*210));
return randomValueY;
}
target: head;
properties: "y";
to: randomize(randomValueY);
duration: 700;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
}
}
}
The problem is that the values of the to properties of the two NumberAnimation instances are bound only once during initialization of the QML component. They are not recalculated when you call animateHead.start() and animations are only executed if the value of the to property differs from the actual value of the animated property. That's why it works only the first time.
A working solution would be:
import QtQuick 1.0
Image {
id: head;
source: "vlad.png";
height: 80;
width: 90;
MouseArea {
anchors.fill: parent
onClicked: {
xAnimation.to = Math.floor(Math.random()*210)
yAnimation.to = Math.floor(Math.random()*210)
animateHead.start();
}
ParallelAnimation {
id: animateHead;
NumberAnimation {
id: xAnimation
target: head;
properties: "x";
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
NumberAnimation {
id: yAnimation
target: head;
properties: "y";
duration: 1000;
easing {
type: Easing.OutBack;
overshoot: 5
}
}
}
}
}
Here the values of the to properties are set explicitly in the onClicked handler of the MouseArea.
Just as a note, because I was trying to solve similar problem, googled this question and decided that there must be another way of dealing with animated property initialization. In Qt 5 you can use the PropertyAction to instantly initialize some properties.
Example from PropertyAction type documentation:
SequentialAnimation {
PropertyAction { target: img; property: "opacity"; value: .5 }
NumberAnimation { target: img; property: "width"; to: 300; duration: 1000 }
PropertyAction { target: img; property: "opacity"; value: 1 }
}
I don't know how would it interact with ParallelAnimation but it works very good with SequentialAnimation.

Resources