qml开发笔记(五): 可视化元素BorderImage、AnimatedImage、AnimatedSprite、SpriteSequence

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/78542856
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

目录

前话

关于Sprites精灵动画

BorderImage

描述

属性

AnimatedImage

描述

属性

AnimatedSprite

描述

属性

方法

示例

SpriteSequence

描述

属性

方法

入坑

示例


红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)

Qt开发专栏:qml开发(点击传送门)

 

    qml开发笔记(五): 可视化元素BorderImage、AnimatedImage、AnimatedSprite、SpriteSequence

 

前话

        上一章节介绍了可视化元素Rectangle和Image。本章节将继续学习可视化元素BorderImage、AnimatedImage、AnimatedSprite和SpriteSequence。

        BorderImage是单个图像分区域缩放;

        AnimatedImage是播放gif;

        AnimatedSprite是精灵动画;

        SpriteSequence本人认为非常有必要认真阅读,实现了游戏当中的走路,代码很简单,原理是sprites精灵动画。

 

关于Sprites精灵动画

        qml的sprites可参照css的sprites,我们可以把一个精灵当作一个动画。

        CSSSprites在国内很多人叫CSS精灵,其实这个技术不新鲜,原理就是:靠不断的切换图片让人感觉视觉上不断在变化,例如gif动画之类的效果,前端实现精灵效果原理有两种方式:

        第一种:传统的就是靠定时器不断去改变一个元素的background-image属性了,简单的来说就是靠不断的替换图片,但是值得注意的问题就是图片如果很多,加载会比较慢,会占用大量网络资源。

        第二种:大多数的做法就是把图片都合成一张大图再利用CSS的属性(background-image、background-repeat、background-position)组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。

 

BorderImage

描述

        本元素用于创建有边框分割的图像,图像可缩放和平铺其中的每个部分。一个本元素可将图片分成9个区域,如下图:

        1.    角区域1/3/7/9是不会缩放的;

        2.    区域2和8缩放是依赖horizontalTileMode

        3.    区域4和6缩放是依赖verticalTileMode

        4.    区域5缩放是依赖horizontalTileModeverticalTileMode

属性

  • asynchronous  : bool [指定本地文件系统上的图像应在单独的线程中异步加载。默认值为false,导致用户界面线程在加载图像时阻塞。将异步设置为true对保持响应性用户界面比立即可见图像更可取] (注意:此属性只对从本地文件系统读取的图像有效。通过网络资源(例如HTTP)加载的图像总是异步加载。)
  • border [该边界是将borderImage分割城9个区域的边界]
Rectangle {
    Image {
        source: "3.png";
    }
    BorderImage {
        x:150;
        source: "3.png";
        width: 200; height: 200;
        border.left: 35; border.top: 35;
        border.right: 35; border.bottom: 35;
    }
    BorderImage {
        x:400;
        source: "3.png";
        width: 200; height: 200;
        border.left: 45; border.top: 45;
        border.right: 45; border.bottom: 45;
    }
    BorderImage {
        x:650;
        source: "3.png";
        width: 200; height: 200;
        horizontalTileMode: BorderImage.Repeat
        border.left: 35; border.top: 35;
        border.right: 35; border.bottom: 35;
    }
    BorderImage {
        x:900;
        source: "3.png";
        width: 200; height: 200;
        horizontalTileMode: BorderImage.Round
        border.left: 35; border.top: 35;
        border.right: 35; border.bottom: 35;
    }
}

  • border.left : int [参照上面]
  • border.right : int [参照上面]
  • border.top : int [参照上面]
  • border.bottom : int [参照上面]
  • cache : bool [指定是否应缓存图像。默认值为true。在处理大型图像时,将缓存设置为false是很有用的,以确保它们不会以牺牲小UI元素的图像为代价进行缓存]
  • horizontalTileMode : enumeration [如何重复或拉伸边界图像的中间部分,缺省为Stretch]
BorderImage.Stretch - Scales the image to fit to the available area.
BorderImage.Repeat  - Tile the image until there is no more space. May crop the last image.
BorderImage.Round   - Like Repeat, but scales the images down to ensure that the last image is not cropped.

  • mirror : bool [rotation为0度时,以纵轴为轴心,做镜像,缺省false]
  • progress : real [这个属性保存图像的加载进度,从0(无负载)到1(完成)]
  • smooth : bool [此属性保存缩放或转换时图像是否平滑地过滤。平滑过滤提供了更好的视觉质量,但在某些硬件上可能会慢一些。如果图像以自然大小(本身大小)显示,则此属性没有视觉效果或性能效果。默认情况下,此属性设置为true]
  • source : url [映像可以处理Qt支持的任何图像格式,它由Qt支持的任何URL方案加载。URL可能是绝对的,或者与组件的URL相对]
  • sourceSize : QSize[此属性包含加载图像的实际宽度和高度。与宽度和高度缩放的属性不同,此属性设置存储的图像的实际像素数,以便大图像不使用比必要的更多内存,参照Image元素的例子,保证图像在内存不大于1024x1024像素]
  • status : enumeration [这个属性保存图像的加载状态]
Image.Null       - no image has been set  
Image.Ready    - the image has been loaded  
Image.Loading  - the image is currently being loaded  
Image.Error      - an error occurred while loading the image  

 

AnimatedImage

描述

 

    Animatedimage提供一种方式来播放存储包含一系列的帧的图像动画,如存储图像的gif文件。

Rectangle {
    width: animation.width;
    height: animation.height + 8;
    color: "black";
    AnimatedImage {
        id: animation;
        source: "4.gif";
    }
    Rectangle {
        // 下句报错"depends on non-NOTIFYable properties:
        //              QQuickAnimatedImage::frameCount"
        // rectangle不显示
//        property int frames: animation.frameCount; // 报错语句
        width: 4; height: 8
//        x: (animation.width - width) * animation.frames / frames;  // 报错语句
        x: (animation.width - width) * animation.currentFrame / animation.frameCount
        y: animation.height
        color: "red"
    }

属性

  • currentFrame : int [当前正在显示的帧的序号]
  • frameCount : int [帧的总数]
  • paused : bool [暂停,播放成功后暂停会停止播放,paused前提是playing为true,每次playing从false变为true,paused会自动变为false]
  • playing : bool [播放中,当成功加载图像后,变为true,用以标志图像加载结果]
  • source : url [gif地址]

 

AnimatedSprite

描述

        Animatedsprite提供渲染和提供了在同一个图像文件的多个帧的动画控制。可以以固定的速度播放,以显示的帧速率,或手动推进和控制进度。

属性

  • currentFrame : int [当暂停时,可手动设置当前帧或者使用advance()推进一帧]
  • frameCount : int [总帧数]
  • frameDuration : int [每一帧动画的间隔,当等于或小于0时无效;如果frameRate有效,frameRate则会被用于计算该帧的持续时间;如果frameRate无效,但frameDuration有效,那么将使用frameDuration,注意:更改此参数将重新启动动画]
  • frameHeight : int [单帧高度,如果都一样则唯一的,则可忽略]
  • frameRate : qreal [每秒显示的动画帧数,当等于或小于0时无效;如果frameRate有效,frameRate则会被用于计算该帧的持续时间;如果frameRate无效,但frameDuration有效,那么将使用frameDuration,注意:更改此参数将重新启动动画]
  • frameSync : bool [如果为真,则动画将没有持续时间。每次一帧渲染到屏幕时,动画将前进一帧。这使它与绘画速度同步,而不是经过时间。如果framesync设置为true,它将重写的帧率和frameduration。默认为false。更改此参数将重新启动动画]
  • frameWidth : int [单帧宽度,如果都一样则唯一的,则可忽略]
  • frameX : int [在animatedsprite第一帧图像文件的x坐标。如果第一帧在文件左上角开始,则可以忽略]
  • frameY : int [在animatedsprite第一帧图像文件的y坐标。如果第一帧在文件左上角开始,则可以忽略]
  • interpolate : bool [如果为true,则在精灵帧之间会出现插值,使动画看起来更平滑(前一张渐隐后一张渐显)。默认为true]
  • loops : int [动画多次播放后,动画会自动停止。负值是无效的。如果设置为AnimatedSprite.Infinite,动画将会无限循环播放,且默认是无限AnimatedSprite.Infinite]
  • paused : bool [暂停时,当前帧可以手动更新,默认为false。]
  • reverse : bool [是否反向播放,默认为false]
  • running : bool [是否正在播放动画,默认为true]
  • source : url [动画地址]

方法

  • int advance() [前进一帧]
  • int pause() [暂停]
  • int restart() [重新播放]
  • int resume() [暂停后的恢复播放]

示例

Rectangle {
    visible: true;
    width: 360;
    height: 320;
    color: "white";
    Image {
        id:image
        source: "./6.png"
        x:350
    }
    AnimatedSprite {
        id: animated;
        width: image.width/3;  // 显示窗口宽度
        height: image.height/2; // 显示窗口高度
        anchors.centerIn: parent;
        source: "6.png";
        frameWidth: image.width/4;
        frameHeight: image.height/3;
        frameDuration: 200;
        frameCount: 16;
        frameX: 0;
        frameY: 0;
        onCurrentFrameChanged: {
            info.text = "%1/%2".arg(animated.currentFrame).arg(animated.frameCount);
        }
    }
    Row{
        spacing: 4;
        anchors.horizontalCenter: parent.horizontalCenter;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        Text {
            id: info;
            width: 60;
            height: 24;
            color: "red";
            verticalAlignment: Text.AlignVCenter;
            horizontalAlignment: Text.AlignRight;
        }

        Button {
            width: 60;
            height: 24;
            text: (animated.paused == true) ? "Play" : "Pause";
            onClicked: (animated.paused == true) ? animated.resume() : animated.pause();
        }
        Button {
            width: 70;
            height: 24;
            text: "Advance";
            onClicked: animated.advance();
        }
        Button {
            width: 70;
            height: 24;
            text: "Restart";
            onClicked: animated.restart();
        }
        Button {
            width: 60;
            height: 24;
            text: "Quit";
            onClicked: Qt.quit();
        }
    }
}

运行时,Quit无法退出,报出错误:” Signal QQmlEngine::quit()emitted, but no receivers connected to handle it.”。因为本人采用的是在QtGui中加载qml,不是纯qml应用,所以qml需要与QtGui中的信号相关联;在QtGui中加入代码:

void MainWindow::initQmlWidget()
{
    // 初始化quick窗口
    _pQuickView = new QQuickView();
    _pQuickView->setSource(QUrl("./qml/start.qml"));
    _pQuickWidget = QWidget::createWindowContainer(_pQuickView, this);
    _pQuickWidget->hide();
    // 用于与qml交互
    _pQmlContext = _pQuickView->rootContext();
    // 显示qml
    _pQuickWidget->show();
    // 代码补充处: QtGui 与 qml 退出信号关联
    QObject::connect(_pQuickView->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
}

 

SpriteSequence

描述

        用于作为一系列帧存储的多个动画之间的播放和转换。

属性

  • currentSprite : string [只读][当前正在播放的精灵动画名字,只读,只有在暂停时才可以设置]
  • goalSprite : string [下一个播放的精灵动画名字,如果有可能从目标状态的起始点返回到目标状态,那么它将继续这样做(不断0->goalSprite循环),直到目标状态被设置为“”或一个不可到达的状态]
  • interpolate : bool [切换过渡优化,默认true]
  • running : bool [是否正在播放精灵,默认为true]
  • sprites : list<Sprite> [精灵播放列表,播放时精灵将会被缩放到这个项目的大小]

方法

  • jumpTo(string sprite) [这个函数会导致立即跳转到指定的精灵,中间的精灵不会被播放。精灵的参数是你想要跳转到的精灵的名字]

入坑

捕捉键盘时,若一直按下按钮,会在短暂的停滞后Release然后不断的OnPressed和OnRelease,等同于连续敲击,这点与传统的桌面应用程序不一样。

示例

        实现一个动画,按方向键上下左右,可以走动,松下就停止,效果如下图:

Rectangle {
    visible: true;
    width: 240;
    height: 200;
    color: "black";
    Image {
        x:100;
        id: image1;
        source: "./11.png";
    }
    SpriteSequence {
        id: sequence;
        width: 100;
        height: 100;
        interpolate: true;
        running: false;
        sprites: [
            Sprite {
                name: "down";
                source: image1.source;
                frameCount: 4;
                frameWidth: image1.width/4;
                frameHeight: image1.height/4;
                frameRate: 10;
            },
            Sprite {
                name: "left";
                source: image1.source;
                frameCount: 4;
                frameY: image1.height/4;
                frameWidth: image1.width/4;
                frameHeight: image1.height/4;
                frameRate: 10;
            },
            Sprite {
                name: "right";
                source: image1.source;
                frameCount: 4;
                frameY: image1.height/4*2;
                frameWidth: image1.width/4;
                frameHeight: image1.height/4;
                frameRate: 10;
            },
            Sprite {
                name: "up";
                source: image1.source;
                frameCount: 4;
                frameY: image1.height/4*3;
                frameWidth: image1.width/4;
                frameHeight: image1.height/4;
                frameRate: 10;
            }
        ]
    }
    focus: true; // 不获取焦点是无法获取键盘的
    Keys.onPressed: { // 当持续按住up时,将会变成多次连击,不断pressed和release
        switch(event.key)
        {
        case Qt.Key_Up: // false时,跳转到"up",此时无法不跑,再将SpriteSequence.running设置true
            sequence.jumpTo("up");
            sequence.running = true;
            text.text = "按下方向键上,正在向上走路";
            break;
        case Qt.Key_Down:
            sequence.jumpTo("down");
            sequence.running = true;
            text.text = "按下方向键下,正在向下走路";
            break;
        case Qt.Key_Left:
            sequence.jumpTo("left");
            sequence.running = true;
            text.text = "按下方向键左,正在向左走路";
            break;
        case Qt.Key_Right:
            sequence.jumpTo("right");
            sequence.running = true;
            text.text = "按下方向键右,正在向右走路";
            break;
        default:
            ;
        }
    }
    Keys.onReleased: {
        sequence.running = false;
        text.text = "请按方向键走路:上、下、左、右";
    }
    Text {
        id: text;
        y:200;
        anchors.horizontalCenter: parent.horizontalCenter;
        text:"请按方向键走路:上、下、左、右";
    }
}

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/78542856

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙红胖子Qt(长沙创微智科)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值