若该文为原创文章,未经允许不得转载
原博主博客地址: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、单片机、软硬结合等等)持续更新中...(点击传送门)
上一章节介绍了可视化元素Rectangle和Image。本章节将继续学习可视化元素BorderImage、AnimatedImage、AnimatedSprite和SpriteSequence。
BorderImage是单个图像分区域缩放;
AnimatedImage是播放gif;
AnimatedSprite是精灵动画;
SpriteSequence本人认为非常有必要认真阅读,实现了游戏当中的走路,代码很简单,原理是sprites精灵动画。
qml的sprites可参照css的sprites,我们可以把一个精灵当作一个动画。
CSSSprites在国内很多人叫CSS精灵,其实这个技术不新鲜,原理就是:靠不断的切换图片让人感觉视觉上不断在变化,例如gif动画之类的效果,前端实现精灵效果原理有两种方式:
第一种:传统的就是靠定时器不断去改变一个元素的background-image属性了,简单的来说就是靠不断的替换图片,但是值得注意的问题就是图片如果很多,加载会比较慢,会占用大量网络资源。
第二种:大多数的做法就是把图片都合成一张大图再利用CSS的属性(background-image、background-repeat、background-position)组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。
本元素用于创建有边框分割的图像,图像可缩放和平铺其中的每个部分。一个本元素可将图片分成9个区域,如下图:
1. 角区域1/3/7/9是不会缩放的;
2. 区域2和8缩放是依赖horizontalTileMode;
3. 区域4和6缩放是依赖verticalTileMode;
4. 区域5缩放是依赖horizontalTileMode和verticalTileMode;
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;
}
}
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.
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提供一种方式来播放存储包含一系列的帧的图像动画,如存储图像的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"
}
Animatedsprite提供渲染和提供了在同一个图像文件的多个帧的动画控制。可以以固定的速度播放,以显示的帧速率,或手动推进和控制进度。
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()));
}
用于作为一系列帧存储的多个动画之间的播放和转换。
捕捉键盘时,若一直按下按钮,会在短暂的停滞后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