QML::图像、状态、动画

QML图像、状态、动画

1.01 渐变
1. 在QM中使用Gradient项目来定义一个渐变。
2. 渐变中的颜色使用一组 GradientStop子项目进行定义,它们每一个都在渐变中定义了一个从0.0~1.0之间的位置和一个颜色。
3. 每一个GradientStop都可以通过position属性来设置位置,通过color属性来设置颜色。
Rectangle {
    width: 100; height: 100
    gradient: Gradient {
        GradientStop { position: 0.0; color: "red" }
        GradientStop { position: 0.33; color: "yellow" }
        GradientStop { position: 1.0; color: "green" }
    }
}
1.02 图片Image
1. QML中的Image元素用来在声明式用户界面中显示图片。
2. 图片资源使用source属性作为一个URL来指定,这里可以应用Qt支持的所有格式,包括PNGJPEG和SVG等。
3. 如果width和height属性没有被指定,那么Image 元素自动使用加载默认的的图片的大小。
4. 如果指定了Image的大小,那么图片会缩放到这个大小。这个行为也可以通过设置fillMode属性来改变,它允许图片进行拉伸或者平铺。
填充属性:
fillMode:lmage.PreserveAspectCrop
如:
lmage.stretch:默认值。缩放图像以适合项目
lmage.PreserveAspectFit:图像均匀缩放以适应而不裁剪
lmage.PreserveAspectCrop:图像均匀缩放以填充,必要时进行裁剪
Image.Tile:水平和垂直复制图像
Image.TileVertically:图像水平拉伸并垂直平铺
lmage.TileHorizontally:图像被垂直拉伸并水平平铺
lmage.Pad:图像未转换
1. 本地的图片会被立即加载,而且在加载完成以前用户界面会被阻塞。
2. 如果要加载一个巨大的图片,最好是在一个低优先级的线程中进行,这可以通过将asynchronous属性设置为true来实现。
 Image {
        width: 100; height: 100
        fillMode: Image.TileHorizontally
        source: '../image/125.png'
}
1. 图片需要从网络上获取而不是本地资源,那么它会自动在其他线程中异步加载,
2. progress和status属性会在合适的时间进行更新。
3. 如果在几个Image元素中使用了相同的source,图片会在内部进行缓存和共享,那么只会加载该图片的一个备份。
4. 图片一般是QML用户界面中最占内存的,所以建议将不是界面的组成部分的图片使用sourceSize属性设置其大小。
5. sourceSize属性可以设置sourceSize.width和sourceSize.height,这个属性会设置加载的图片保存时的真实像素数量,这样巨大的图片也不会使用太多的内存了。
6. 与Image的widthheight属性不同,因为设置Image的widthheight属性会在绘制图片时进行缩放。

Image {
    id: image
    width: 120; height: 120
    fillMode: Image.Tile
    source: "http://www.baidu.com/img/baidu_sylogo1.gif"
    sourceSize.width: width
    sourceSize.height: height
    onStatusChanged: {
        if (image.status == Image.Ready)
            console.log('Loaded')
        else if(image.status == Image.Loading)
            console.log('Loading')
    }
}
1.03 边界图片 BorderImage
BorderImage元素通过缩放或者平铺图片的各个部分来创建超出图片的边界,
一个BorderImage元素将一个源图片分成9个区域:
(1)4个角(1379区域)不进行缩放
(2)区域28通过horizontalTileMode属性设置的模式进行缩放
(3)区域46通过verticalTileMode属性设置的模式进行缩放
(4)中间部分(区域5)会结合 horizontalTileMode 和 verticalTileMode 属性设置的模式进行缩放。

image

这些区域可以使用图片的border属性组来进行定义,该属性指定了到源图片每个边缘的距离作为边界。上
下左右4条边界线分别是border.topborder.bottomborder.leftborder. right。
可用的平铺模式有:
BorderImage.Stretch 拉伸、
Borderlmage.Repeat 平铺,但可能修剪最后的图片、
BorderImage.Round 进行平铺但是将图片进行缩小来确保最后的图片不进行修剪。
1.04 动态图片 AnimatedImage
AnimatedImage扩展了Image元素的功能,可以用来播放包含了一系列帧的图片动画,比如GIF文件。
当前帧和动画总长度等信息可以使用currentFrame和frameCount属性来获取。
可以通过改变playing和paused属性的值来开始、暂停和停止动画。
Rectangle {
    width: animation.width; height: animation.height + 8

    AnimatedImage { id: animation; source: "../image/animation.gif" }

    Rectangle {
        property int frames: animation.frameCount

        width: 4; height: 8
        x: (animation.width - width) * animation.currentFrame / frames
        y: animation.height
        color: "red"
    }
}
1.05 缩放、旋转和平移
1. Item元素拥有一个scale属性和一个rotation属性,分别可以实现项目的缩放和旋转。
cale的默认值是1, 显示正常大小。
2. scale值小于1, 那么会将项目缩小显示。
3. scale值大于1, 那么会将项目放大显示。
4. scale值是负值, 那么将会显示镜像效果。
缩放是以transformOrigin属性指定的点为原点进行的,可用的点一共有9个,
默认的原点是Center即项目的中心。
如果想使用任意的点作为原点,那么就要使用后面讲到的Scale和Rotation元素了。

image

Rectangle {
   color: 'red'
   x: 25; y:25; width: 25; height: 25
   scale: 1.6
   rotation: 30
   transformOrigin: 'TopLeft'
}
1. Item还有一个 transform 属性,需要指定一个 Transform 元素的列表。
2. Transform元素是一个基本类型,无法被直接实例化,可用的Transform类型有3个:
Rotation、
Scale、
Translate,分别用来进行旋转、缩放和平移。
这些元素可以通过专门的属性来进行更加高级的变换设置。
3. Rotation提供了坐标轴和原点属性,坐标轴有 axis.x、axis.y和axis.z分别代表X轴、Y轴和Z轴,也就是说可以实现3D效果。原点由origin.x和origin.y来指定。
4. 简单的2D旋转是不需要指定坐标轴的,默认使用Z轴(axis(x:0;y:0;z:0))即可。
5. 对于典型的3D旋转,既需要指定原点,也需要指定坐标轴。
6. 使用angle属性可以指定顺时针旋转的度数。
Rectangle {
    width: 100; height: 100
    color: "blue"
    transform: Rotation { origin.x: 30; origin.y: 30; axis { x: 0; y: 1; z: 0 } angle: 72 }
}
在Scale 中提供了origin.x和origin.y属性来设置原点,
另外还可以使用xScale和yScale来分别设置X轴和Y轴的比例因子,就是在X轴方向和Y轴方向的缩放值。
如:将红色矩形在X轴方向放大了3倍。
Rectangle {
    width: 100; height: 100
    color: "blue"
    Rectangle {
        width: 50; height: 50; x: 20; y: 20
        color: "red"
        transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
    }
}
Translate中提供了x和y属性来分别设置在X轴和Y轴方向的偏移量。
如:将两个矩形在轴方向进行了向上和向下的偏移。
Row {
    Rectangle {
        width: 100; height: 100
        color: "blue"
        transform: Translate { y: 20 }
    }
    Rectangle {
        width: 100; height: 100
        color: "red"
        transform: Translate { y: -20 }
    }
}

2.01 状态

1. 用户界面用来显示不同场景中的界面,或者是改变它们的外观来响应用户的交互,通常情况下,有一系列变化是并发进行的。
2. 在QML中,任何对象都可以在不同的状态间变化,每一个状态中都可以修改相关项目的属性来显示一个不同的配置。如:
(1)显示一些UI元素以及隐藏一些UI元素
(2)为用户呈现不同的动作
(3)开始、停止或者暂停动画
(4)执行一些需要在新的状态中使用的脚本
(5)为一个特定的项目改变一个属性
(6)显示一个不同的视图或者“场景”
2.02 states属性
1. 所有基于Item的对象都有一个默认状态,还可以使用项目的states属性,通过添加新的State对象来为其指定附加状态。
2. 每一个状态都有一个在本项目中唯一的名称,默认状态的状态名称为空字符串。要改变一个项目的当前状态,可以将state属性设置为要改变到的状态的名称。
3. 对于不是Item派生的对象可以通过StateGroup元素来使用状态。
创建状态:
要创建一个状态,可以向项目的states属性添加一个State对象,states 属性包含了该项目状态的列表。
Rectangle {
    width: 800; height: 600

    Rectangle {
        id: myRect
        width: 200; height: 200
        color: "red"

        MouseArea {
            anchors.fill: parent
            onClicked: myRect.state = 'moved'
        }

        states: [
            State {
                name: "moved"
                PropertyChanges { target: myRect; x: 50; y: 50 }
            }
        ]
    }
}
State不仅限于对属性值进行修改,它还可以:
(1)使用 StateChangeScript 运行一些脚本
(2)使用PropertyChanges为一个对象重写现有的信号处理器
(3)使用 PropertyChanges 为一个项目重定义父项目
(4)使用 AnchorChanges 修改锚的值
2.03 默认状态
1. QML的另一个特色就是可以使项目恢复到默认状态。
2. 在默认状态中包含了项目所有的初始化属性值。
3. 当when属性设置的表达式值为true时,项目会设置为该状态。
4. 使用when属性比使用信号处理器来分配状态更加简单,更符合声明式的语言。
常用的动画类型元素动画:
PropertyAnipation:属性值改变播放动画
NumberAnimation:qreal-type值改变播放动画
ColorAnimation:颜色值改变播放动画
RotationAnimation:旋转值改变播放的动画
可以通过多种方式执行动画:
属性上的动画:在元素完全加载后自动运行.
属性上的行为:属性值更改时自动运行.
独立动画:使用start()显式启动动画或将running设置为true时运行.

3.01 动画

1. 在QML中,可以在对象的属性值上应用动画对象,来随着时间逐渐改变它们,从而创建动画。
2. 动画对象可以从一组内建的动画元素进行创建,可以用来为多种类型的属性值产生动画。
3. 动画对象可以通过不同的方式进行应用,这依赖于它们所需要的背景。
3.02 动画类型
1. Rectangle一旦创建该动画就要将其移动到一个已知的位置;
2. 动画只有在Rectangle被外部源移动时才会触发,例如,当单击鼠标时,产生人动画移动到鼠标位置。
3. 只有在接收到一个特定的信号后才触发该动画。
4. 作为一个独立的动画,虽然没有绑定Rectangle的运动,但是可以从脚本中进行开启和停止。
5. 只有在状态改变时才会触发该动画。
3.03 为了支持这些不同类型的动画方式,QML提供了多种方式来定义一个动画
1. 使用属性值源来创键一个动画,可以立即为一个指定的属性使用动画。
2. 使用行为动画,当一个属性改变值时触发。
3. 在一个信号处理器中创建,当接收到一个信号时触发。
4. 作为一个独立动画,可以在脚本中进行开始/停止,也可以重新绑定到不同的对象;
5. 使用切换,在不同状态间提供动画。
3.04 动画作为属性值的来源
一个动画被应用为属性值源(propertyvaluesource),要使用“动画on属性”语法.
1. Rectangle的x和y属性上应用了PropertyAnimation 来使它们从当前值(0)在1000毫秒中使用动画变化到502. Rectangle一旦加载完成就会开启该动画。要指定一个自定义的值而不是使用当前值作为起始值,可以设置PropertyAnimation的from属性。
3. 这里的 loops 属性指定为 Animation.Infinite,表明该动画是无限循环的。
4. 指定一个动画作为属性值源,在一个对象加载完成后立即就对一个属性使用动画变化到一个指定的值的情况是非常有用的。

Rectangle {
    width: 100; height: 100
    color: "red"
    // 1s内向指定位置移动
    PropertyAnimation on x { to: 50; duration: 1000; loops: Animation.Infinite }
    PropertyAnimation on y { to: 50; duration: 1000; loops: Animation.Infinite }
}
3.05 行为动画
经常在一个特定的属性值改变时,应用到一个动画,在这种情况下,可以使用一Behavior 为一个属性改变指定一个默认的动画。
(1)Rectangle拥有一个Behavior对象应用到了它的x和y属性。
2)每当这些属性改变(这里是在父项目Item中单击时),在Behavior中的PropertyAnimation对象就会应用到这些属性上,从而使Rectangle使用动画效果移动到一个新的位置。
3)行为动画是在每次响应一个值的变化时触发的。
如果x或y绑定到了其他属性上,这些属性改变时也会触发动画。
在一些情况下还可以通过设置enabled属性来停用Behavior。
Item {
    width: 100; height: 100
    Rectangle {
        id: rect
        width: 100; height: 100
        color: "red"
        Behavior on x { PropertyAnimation { duration: 500 } }
        Behavior on y { PropertyAnimation { duration: 500 } }
    }
    MouseArea {
        anchors.fill: parent
        onClicked: { rect.x = mouse.x; rect.y = mouse.y }
    }
}
3.06 在信号处理器中的动画
1. 可以在一个信号处理器中创建一个动画,并在接收到信号时触发。
2. 在这里PropertyAnimation的fromto属性是不需要定义的,因为这些值已经提供了,
分别是Rectangle的当前值和onClicked处理器中设置的新值。
3. 因为动画没有绑定到一个特定的对象或者属性,所以必须指定target和property(或者targets和properties)属性的值。
而且还需要使用 to属性来指定新的x和y的值。
Rectangle {
    id: rect
    width: 100; height: 100
    color: "red"

    MouseArea {
        anchors.fill: parent
        onClicked: PropertyAnimation { target: rect; properties: "x,y"; to: 50; duration: 1000 }
    }
}
3.07 独立动画
1. 动画也可以像一个普通的QML对象一样进行创建,而不需要绑定到任何特定的对象和属性。
2. 一个独立的动画对象默认是没有运行的,必须使用running属性或者start()和stop()函数来明确地运行它。
因为动画没有绑定到一个特殊的对象或属性上,所以必须定义target和property(或者targets和properties)属性的值。
也需要使用t0属性来指定新的x和y的值。
独立动画在不是对一个单一对象属性进行动画而且动画需要明确开始和停止的情况下是非常有用的。
Rectangle {
    id: rect
    width: 100; height: 100
    color: "red"
    PropertyAnimation {
        id: animation
        target: rect
        properties: "x,y"
        duration: 1000
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            animation.to = 50;
            animation.running = true;
        }
    }
}
3.07 Transition对象
切换用来设置当状态改变时的动画,要创建一个切换,需要定义一个Transition对象,
然后将其添加到项目的transitions属性。
import QtQuick 2.0
Rectangle {
    id: root
    width: 800
    height: 600
    MouseArea  {
        id:  mouseArea
        anchors.fill:  parent
        onClicked:  {
            light1.state  =  ( light1.state == 'stop' ? "go" : 'stop' )
            light2.state  =  ( light2.state == 'go' ? 'stop' : 'go' )
            console.log('light1.state : ',light1.state);
            console.log('light2.state : ',light2.state);
        }
    }
    Rectangle  {
        id: light1
        x:24; y:15
        width: 100; height: 100
        radius: width/2
        color:  'black'
		
        states:  [
            State  {
                name:  "stop"
                PropertyChanges  { target:  light1; color:  'red' }
            },
            State  {
                name:  "go"
                PropertyChanges  { target:  light2; color:  'green' }
            }
        ]
	/*状态过度,延时2s*/
        transitions: [
            Transition {
                from: "stop"; to: "go"
                ColorAnimation{ target: light1; properties: 'color'; duration: 2000 }
                ColorAnimation{ target: light2; properties: 'color'; duration: 2000 }
            }
        ]
    }
    Rectangle  {
        id: light2
        x:24; y:135
        width: 100; height: 100
        radius: width/2
        color:  'black'
    }
}
3.08 动画元素
1. 需要在内建的动画元素中选择一个来创建一个动画,虽然在前面的例子中都使用了PropertyAnimation进行演示,
2. 不过也可以根据属性的类型以及是否需要一个或者多个动画来选择使用其他的元素。
3. 所有的动画元素都继承自Animation元素,尽管无法直接创建Animation对象,不过它为动画元素提供了必要的属性和函数。
它允许使用running属性和start()和stop()函数来控制动画的开始和停止,也可以通过loops属性定义动画的循环次数。
3.09 属性动画元素
1. PropertyAnimation是用来为属性提供动画的最基本的动画元素,可以用来为realint,color、rect、point、size和vector3d等属性设置动画,
被NumberAnimation、colorAnimation、RotationAnimation和Vector3dAnimation等元素继承。
2. NumberAnimation对realint属性提供了更高效的实现;
Vector3dAnimation 对 vector3d属性提供了更高效的支持;
ColorAnimation和RotationAnimation分别对color 和rotation属性变化动画提供了特定的属性支持。
ColorAnimation允许颜色值设置fromto属性。
Rectangle {
    width: 100; height: 100
    ColorAnimation on color { from: "red"; to: "yellow"; duration: 1000 }
}
RotationAnimation允许设定旋转的方向。
Rectangle {
    width: 100; height: 100; anchors.centerIn: parent
    color: "red"
    RotationAnimation on rotation { to: 90; direction: RotationAnimation.Clockwise }
}
SmoothedAnimation:它是一个专门的 NumberAnimation,当目标值改变时在动画中为其提供了一个平滑的变化;
SpringAnimation:提供了一个像弹簧一样的动画,可以设置 mass、damping和epsilon等属性;
ParentAnimation:用来在改变父项目时产生动画(对应ParentChange元素);
AnchorAnimation:用来在改变锚时产生动画(对应AnchorChanges 元素);

Rectangle {
    width: 100; height: 100
    color: "red"

    PropertyAnimation on x { to: 50; duration: 1000; easing.type: Easing.OutBounce }
    PropertyAnimation on y { to: 50; duration: 1000; easing.type: Easing.OutBounce }
}
3.10组合动画
1. 多个动画可以组合成一个单一的动画,这可以使用ParallelAnimation或者SequentialAnimation动画组元素中的一个来实现。
2. 在ParallelAnimation中的动画会同时进行,而在 SequentialAnimation中的动画会一个接一个地运行。
要想运行多个动画,可以在一个动画组中定义。
Rectangle {
    id: rect
    width: 120; height: 200

    Image {
        id: img
        source: "../image/125.png"
        anchors.horizontalCenter: parent.horizontalCenter
        y: 0

        SequentialAnimation on y {
            loops: Animation.Infinite
            NumberAnimation { to: rect.height - img.height;
                easing.type: Easing.OutBounce; duration: 2000 }
            PauseAnimation { duration: 1000 }
            NumberAnimation { to: 0; easing.type: Easing.OutQuad;
                duration: 1000 }
        }
    }
}
因为SequentialAnimation是应用在y属性上的,所以在组中的独立的动画也会自动应用在y属性上。动画组还可以嵌套,下面的例子是一个相对复杂的动画,它同时使用了顺序和并行动画。

一旦独立的动画被放人 SequentialAnimation或者ParallelAnimation,那么它们就不能再独立开启或者停止。
顺序或者并行动画必须作为一个组进行开启和停止。
Rectangle {
    id: redRect
    width: 100; height: 100
    color: "red"

    MouseArea { id: mouseArea; anchors.fill: parent }

    states: State {
        name: "pressed"; when: mouseArea.pressed
        PropertyChanges { target: redRect; color: "blue";
            y: mouseArea.mouseY; width: mouseArea.mouseX }
    }

    transitions: Transition {

        SequentialAnimation {
            ColorAnimation { duration: 200 }
            PauseAnimation { duration: 100 }

            ParallelAnimation {
                NumberAnimation {
                    duration: 500
                    easing.type: Easing.OutBounce
                    targets: redRect
                    properties: "y"
                }

                NumberAnimation {
                    duration: 800
                    easing.type: Easing.InOutQuad
                    targets: redRect
                    properties: "width"
                }
            }
        }
    }
}
3.11 其他动画元素
QML还为动画提供了其他一些有用的元素:
1. PauseAnimation:在动画中间进行暂停;
2. ScriptAction:允许在动画中执行JavaScript,也可以和 StateChangeScript 一起使用来重用已经存在的脚本;
3. PropertyAction:在动画中间立即改变一个属性而不对该属性的变化使用动画。
3.12 弹动效果Flickable
1. QML中提供了一个Flickable元素,它可以将其子项目设置在一个可以拖拽和弹动的界面上,使得子项目的视图可以滚动。
这种行为构成了被设计用来显示大量子项目元素的基础,例如ListView和GridView。
2. 在传统的用户界面中,视图可以使用滚动条和箭头按钮等标准控件来滚动。
在某些情况下,也可以按下鼠标按钮的同时移动光标来拖动视图。
但是在基于触摸的用户界面中,拖拽动作经常使用弹动动作来实现,当用户已经停止触摸视图后它还会继续滚动。
3. Flickable不会自动裁剪它的内容,如果不是将它用作全屏项目,可以将clip属性设置为true来隐藏超出区域的内容。
contentWidth和contentHeight属性用来设置可以进行拖拽的内容的大小,这个一般设置为要在Flickable中显示内容的整体大小。
只在一个区域中显示Flickable元素,这时为了不让其在指定区域以外显示,将其clip属性设置为true。

Flickable {
    width: 200; height: 200
    contentWidth: image.width; contentHeight: image.height
    clip: true
    Image { id: image; source: "../image/bigImage.jpg" }
}
1. 希望在Flickable中显示一个滚动条,这可以通过visibleArea属性来实现.
2. 属性分为 visibleArea.xPosition、visibleArea. widthRatio、visibleArea. yPosition和 visibleArea.heightRatio。
3. 它们都是只读属性,描述了当前可视区域的位置和大小。大小被定义为当前可视窗口占整个视图的百分比,从0.0到1.0。
4.页面位置一般是从0.0到1.0减去大小比,如yPosition的范围是 ((0.0~1.0) - heightRatio)
然而,内容可以拖拽到正常的范围之外,所以页面位置也可能在正常范围之外。
5. 使用flickDeceleration可以设置弹动的速度,使用flickableDirection可以设置弹动的方向等。
对于Flickable 元素其他的属性和信号的使用,可以参考其帮助文档。
Rectangle {
    width: 300; height: 300

    Flickable {
        id: flickable
        width: 300; height: 300
        contentWidth: image.width; contentHeight: image.height
        clip: true

        Image { id: image; source: "../image/bigImage.jpg" }
    }

    Rectangle {
        id: scrollbar
        anchors.right: flickable.right
        y: flickable.visibleArea.yPosition * flickable.height
        width: 10
        height: flickable.visibleArea.heightRatio * flickable.height
        color: "black"
    }
}
3.13 翻转效果 Flipable
1. Flipable是一个可以明显在其正面和反面之间进行翻转的项目,就像一张卡片。
这是通过同时使用Rotation、State和Transition等元素来产生翻转效果的。
2. front和back属性分别用来保存要显示在Flipable项目正面和反面的项目。
3. Flipable项目,每当单击它时都会翻转,且围绕y轴进行旋转:
Flipable有一个flipped布尔值属性,每当在Flipable中的MouseArea上单击鼠标时都会切换该属性的值。
当flipped为true时,项目变为back状态,在这个状态,Rota-tion的angle属性改变为180°来产生一个翻转效果。
当flipped为false时,项目恢复到默认状态,这时angle的值为0。
Flipable {
    id: flipable
    width: 240
    height: 240

    property bool flipped: false

    front: Image { source: "../image/front.png"; anchors.centerIn: parent }
    back: Image { source: "../image/back.png"; anchors.centerIn: parent }

    transform: Rotation {
        id: rotation
        origin.x: flipable.width/2
        origin.y: flipable.height/2
        axis.x: 0; axis.y: 1; axis.z: 0
        angle: 0
    }

    states: State {
        name: "back"
        PropertyChanges { target: rotation; angle: 180 }
        when: flipable.flipped
    }

    transitions: Transition {
        NumberAnimation { target: rotation; property: "angle"; duration: 4000 }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: flipable.flipped = !flipable.flipped
    }
}
posted @   osbreak  阅读(207)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示