I'm trying to create TableView with rows that can expand and show some content on click. It works, but does not show height property animation. I tried to add ColorAnimation and change expanded row color to black and it works well, but for some reason it does not work for height.
Here is the code of my table view:
TableView {
id: myTableView
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 12
anchors.rightMargin: 10
model: myModel
ListModel {
//...
}
rowDelegate: Item {
id: myRowDelegate
Rectangle {
id: rect
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
color: styleData.alternate ? "#d9e5ea" : "white"
MouseArea {
anchors.fill: parent
onClicked: {
myRowDelegate.state = (myRowDelegate.state == "COLLAPSED") ? "EXPANDED" : "COLLAPSED";
console.log("click");
}
}
}
state: "COLLAPSED"
states: [
State {
name: "COLLAPSED"
PropertyChanges { target: myRowDelegate; height: 22; }
},
State {
name: "EXPANDED"
PropertyChanges { target: myRowDelegate; height: 400; }
// PropertyChanges { target: rect; color: "black"; }
}
]
transitions: [
Transition {
from: "EXPANDED"
to: "COLLAPSED"
PropertyAnimation { property: height; duration: 400; }
// ColorAnimation { duration: 400; }
},
Transition {
from: "COLLAPSED"
to: "EXPANDED"
PropertyAnimation { property: height; duration: 400; }
//ColorAnimation { duration: 400; }
}
]
}
}
}
You have to use property name as a string to make it work:
PropertyAnimation { property:"height"; duration: 400; }
You could also achieve that via Behavior (remove transitions for that):
Behavior on height {
NumberAnimation { duration: 400 }
}
Related
I am trying to move an item in my QML off-screen using a transition with AnchorChanges, like so:
Item {
id: view
Repeater {
id: repeater
model: 1
Rectangle {
id: card
property int index
color: "red"
radius: 10
width: parent.width * 0.9
height: parent.height * 0.7
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: units.gu(8)
states: [
State {
name: "hidden"
AnchorChanges { target: card; anchors.top: view.bottom }
}
]
transitions: Transition {
AnchorAnimation { duration: 5000 }
}
Component.onCompleted: card.state = "hidden"
}
}
}
I am using a Repeater because there will be several cards, which I want to move off-screen.
However, when I use the Repeater as shown above, there will be no animation. Instead, after a delay of 5 seconds, the card will be instantly hidden.
If I instead remove the repeater, the animation will be shown:
Item {
id: view
Rectangle {
id: card
property int index
color: "red"
radius: 10
width: parent.width * 0.9
height: parent.height * 0.7
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: units.gu(8)
states: [
State {
name: "hidden"
AnchorChanges { target: card; anchors.top: view.bottom }
}
]
transitions: Transition {
AnchorAnimation { duration: 5000 }
}
Component.onCompleted: card.state = "hidden"
}
}
Whats the reason for this?
With Qt Quick, I created a custom button which looks like that:
This button also contains several states (default, hover, pressed), and the transition between each states is animated. I found a way to animate each properties easily with the Qt Quick engine, except for the image one. Indeed, I want to animate the image transition, by performing a crossfade between states.
However I couldn't found a such animator for images. The only way I found was to add 3 images to my button, one for each states, and to animate their respective opacity.
Below is the code for my buttons:
Button
{
property bool hoveredBtn: false
property bool pressedBtn: false
id: btAnimStateDemo
height: 40
anchors.right: parent.right
anchors.rightMargin: 5
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 290
state: "DEFAULT"
// the button background
background: Rectangle
{
id: btAnimStateDemoBg
anchors.fill: parent
}
// the button text
Text
{
id: btAnimStateDemoText
text: qsTr("A button showing animated states (default, hovered, pressed)")
renderType: Text.NativeRendering
font.bold: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
}
Image
{
id: btAnimStateDemoDefaultImage
width: 30
height: 30
anchors.left: parent.left
anchors.leftMargin: 5
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
opacity: 1.0
source: "Resources/Palette.svg"
}
Image
{
id: btAnimStateDemoHoverImage
width: 30
height: 30
anchors.left: parent.left
anchors.leftMargin: 5
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
opacity: 0.0
source: "Resources/Smile.svg"
}
Image
{
id: btAnimStateDemoPressedImage
width: 30
height: 30
anchors.left: parent.left
anchors.leftMargin: 5
anchors.bottom: parent.bottom
anchors.bottomMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
opacity: 0.0
source: "Resources/Woman.svg"
}
// the component state array
states:
[
State
{
name: "DEFAULT"
PropertyChanges { target: btAnimStateDemoBg; color: "green"}
PropertyChanges { target: btAnimStateDemoBg; radius: 4}
PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 1.0}
PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 0.0}
PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 0.0}
},
State
{
name: "HOVERED"
PropertyChanges { target: btAnimStateDemoBg; color: "red"}
PropertyChanges { target: btAnimStateDemoBg; radius: 10}
PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 0.0}
PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 1.0}
PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 0.0}
},
State
{
name: "PRESSED"
PropertyChanges { target: btAnimStateDemoBg; color: "blue"}
PropertyChanges { target: btAnimStateDemoBg; radius: 15}
PropertyChanges { target: btAnimStateDemoDefaultImage; opacity: 0.0}
PropertyChanges { target: btAnimStateDemoHoverImage; opacity: 0.0}
PropertyChanges { target: btAnimStateDemoPressedImage; opacity: 1.0}
}
]
// the matching transitions between states
transitions:
[
Transition
{
from: "*"; to: "DEFAULT"
ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
},
Transition
{
from: "*"; to: "HOVERED"
ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
},
Transition
{
from: "*"; to: "PRESSED"
ColorAnimation { property: "color"; easing.type: Easing.Linear; duration: 1000 }
NumberAnimation { properties: "radius, opacity"; easing.type: Easing.Linear; duration: 1000 }
}
]
// the mouse area which will apply the correct state in relation to the current mouse status
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onEntered: {btAnimStateDemo.state = "HOVERED"; btAnimStateDemo.hoveredBtn = true;}
onExited: {btAnimStateDemo.state = btAnimStateDemo.pressedBtn ? "PRESSED" : "DEFAULT"; btAnimStateDemo.hoveredBtn = false;}
onPressed: {btAnimStateDemo.state = "PRESSED"; btAnimStateDemo.pressedBtn = true;}
onReleased: {btAnimStateDemo.state = btAnimStateDemo.hoveredBtn ? "HOVERED" : "DEFAULT"; btAnimStateDemo.pressedBtn = false;}
}
}
The above code works well, and reaches the purpose I planned, but is a little complicated from my point of view. It would be wonderful if an animator like NumberAnimation or ColorAnimation would exist for the images, but I found none.
So my question is: Is there a simpler way to animate an image transition between component states than my above proposed solution? Do Qt Quick propose an animator to reach a such purpose?
Create a SpriteSheet that assigns states to each of the three frames then set the interpolate property to true to have it transition between the images.
Sprite Animations with SpriteSequence
SpriteSequence demonstrates using a sprite sequence to draw an animated and interactive bear. The SpriteSequence object defines five different sprites. The bear is initially in a still state:
Sprite{
name: "still"
source: "content/BearSheet.png"
frameCount: 1
frameWidth: 256
frameHeight: 256
frameDuration: 100
to: {"still":1, "blink":0.1, "floating":0}
}
When the scene is clicked, an animation sets the sprite sequence to the falling states and animates the bear's y property.
SequentialAnimation {
id: anim
ScriptAction { script: image.goalSprite = "falling"; }
NumberAnimation { target: image; property: "y"; to: 480; duration: 12000; }
ScriptAction { script: {image.goalSprite = ""; image.jumpTo("still");} }
PropertyAction { target: image; property: "y"; value: 0 }
}
At the end of the animation the bear is set back to its initial state.
I am creating a custom combobox model in which i need to assign a height of a dropDown list in responsive value. It is on length of items at present so unable to reduce or increase its height as per screen resolution. Here is my code :
Rectangle {
width:150;
height: 60;
Rectangle {
id:comboBox
property variant items: ["Item 1", "Item 2", "Item 3"]
property alias selectedItem: chosenItemText.text;
property alias selectedIndex: listView.currentIndex;
signal comboClicked;
width: 100;
height: 30;
z: 100;
smooth:true;
Rectangle {
id:chosenItem
radius:4;
width:parent.width;
height:comboBox.height;
color: "lightsteelblue"
smooth:true;
Text {
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 8;
id:chosenItemText
text:comboBox.items[0];
font.family: "Arial"
font.pointSize: 14;
smooth:true
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
}
}
}
Rectangle {
id:dropDown
width:comboBox.width;
height:0;
clip:true;
radius:4;
anchors.top: chosenItem.bottom;
anchors.margins: 2;
color: "lightgray"
ListView {
id:listView
height:500;
model: comboBox.items
currentIndex: 0
delegate: Item{
width:comboBox.width;
height: comboBox.height;
Text {
text: modelData
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 5;
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = ""
var prevSelection = chosenItemText.text
chosenItemText.text = modelData
if(chosenItemText.text != prevSelection){
comboBox.comboClicked();
}
listView.currentIndex = index;
}
}
}
}
}
Component {
id: highlight
Rectangle {
width:comboBox.width;
height:comboBox.height;
color: "red";
radius: 4
}
}
states: State {
name: "dropDown";
PropertyChanges { target: dropDown; height:30*comboBox.items.length }
}
transitions: Transition {
NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 1000 }
}
}
}
Please suggest me some solution.
I tries to implement View, which rendering some Component and on change source Component plays fadeout/fadein animation.
My code:
import QtQuick 2.1
Item {
id: componentViewRoot
onOpacityChanged: console.log(opacity)
property Component source: null
PropertyAnimation {
id: fadeout
target: componentViewRoot;
alwaysRunToEnd: true
property: "opacity";
to: 0;
duration: 1000
}
PropertyAnimation {
id: fadein
target: componentViewRoot;
alwaysRunToEnd: true
property: "opacity";
to: 1;
duration: 1000
}
onSourceChanged: {
fadeout.start()
loader.sourceComponent = source;
}
Loader{
id:loader
anchors.fill: parent
onLoaded: fadein.start()
}
}
But it not working (don't plays animation) properly.
Please help me.
UDP:
I want use this View like StackView from QtQuick.Controls without depth.
Some code:
Rectangle {
id: mainObjectRoot
implicitHeight: 440
implicitWidth: 720
color: "#f8f8f8"
ComponentView{
id: compView
height: 265
width: 680
onXChanged: console.log("compView"+x)
onYChanged: console.log("compView"+y)
anchors.right: parent.right
anchors.rightMargin: 20
anchors.bottom: parent.bottom
anchors.bottomMargin: 45
anchors.top: parent.top
anchors.topMargin: 130
anchors.left: parent.left
anchors.leftMargin: 20
source: passwordView
}
Connections{
target: sessionManager
onRequiredPasswordChanged :{
if(sessionManager.requiredPassword){
compView.source = passwordView
}
else{
compView.source = mainview
}
}
}
Component {
id: passwordView
PasswordView{
}
}
Component {
id: helpview
HelpView{
}
}
Component{
id: mainview
MainView{
}
}
Component{
id: settingsview
SettingsView{
}
}
In my example code I want to play transition animation on compView.source changed
For now I was
#ComponentView.qml:
import QtQuick 2.1
Item {
id: componentViewRoot
//#source for setting
property Component source: null
//#item for acces rendering item
property alias item: loader.item
function __changeItem(component){
anim._component = component
anim.start()
}
SequentialAnimation {
id:anim
property Component _component: null
NumberAnimation {
id: fadeout
target: componentViewRoot
alwaysRunToEnd: true
property: "opacity"
from : 1
to: 0
}
PropertyAction{
target: loader
property: "sourceComponent"
value: anim._component
}
NumberAnimation {
id: fadein
target: componentViewRoot
alwaysRunToEnd: true
property: "opacity"
from : 0
to: 1
}
}
onSourceChanged: {
__changeItem(source)
}
Loader{
id:loader
anchors.fill: parent
}
}
I need to have drop-down that opens upwards on clicking on Menu button in QML.
I have tried to use the listview for the same, but in the implementation we are getting drop-down which opens downwards.
Any suggestions with reference to below snippet.
import QtQuick 1.1
Rectangle {
width: 800
height: 480
Rectangle {
id:comboBox
property variant items: ["Red", "Blue", "Green"]
signal comboClicked;
x: 651
y: 344
width: 141
height: 30;
z: 0
smooth:true;
Rectangle {
id:chosenItem
radius:4;
width:parent.width;
height:comboBox.height;
color: "#454b4d"
smooth:true;
Text {
anchors.top: parent.top;
anchors.margins: 8;
id:chosenItemText
x: 11
y: 5
color: "#ffffff"
text:"Menu";
anchors.topMargin: 5
anchors.left: parent.left
anchors.leftMargin: 12
font.family: "Arial"
font.pointSize: 14;
smooth:true
}
MouseArea {
width: 400
height: 30
anchors.bottomMargin: 0
anchors.fill: parent;
onClicked: {
comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
}
}
}
Rectangle {
id:dropDown
width:comboBox.width;
height:0;
clip:true;
radius:4;
anchors.top: chosenItem.bottom;
anchors.margins: 2;
color: "lightblue"
ListView {
id:listView
height:500;
model: comboBox.items
currentIndex: 0
delegate: Item{
width:comboBox.width;
height: comboBox.height;
Text {
text: modelData
anchors.top: parent.top;
anchors.left: parent.left;
anchors.margins: 5;
}
MouseArea {
anchors.fill: parent;
onClicked: {
comboBox.state = ""
chosenItemText.text = modelData;
listView.currentIndex = index;
}
}
}
}
}
states: State {
name: "dropDown";
PropertyChanges { target: dropDown; height:30*comboBox.items.length }
}
transitions: Transition {
NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 1000 }
}
}
}
Try to change the anchors of the dropDown item:
that
anchors.top: chosenItem.bottom;
should become
anchors.bottom: chosenItem.top;