目录
- 1. 引言
- 2. 演示效果
- 3. 代码说明
- 3.1 图片缩放
- 3.2 图片平移
- 3.3 图片旋转
- 3.4 网络图片加载
- 3.5 图片填充模式
- 3.6 图片镜像
- 3.7 图片 Mipmap
- 3.8 动态图播放
- 4. 技术要点
- 4.1 Image 属性速查
- 4.2 变换类型对比
- 4.3 Image vs AnimatedImage
- 5. 工程下载
1. 引言
QML 的 Image 组件提供了丰富的属性和功能,可以轻松实现图片的显示、变换、动画等效果。本文基于示例示例进行整合和优化,包括:
- QML Image 组件详解
- QML 图像变换(缩放、平移、旋转)
由于代码篇幅较长,文章中只显示关键部分,完整代码见下载链接。
2. 演示效果
项目中的 Main.qml 文件使用 Flow 布局展示了八种不同的 Image 实现方案:
- 图片缩放:通过 Slider 控制图片的缩放比例
- 图片平移:鼠标拖拽实现图片平移效果
- 图片旋转:通过 Slider 控制图片旋转角度
- 网络图片加载:异步加载网络图片,显示加载状态
- 图片填充模式:演示六种不同的 fillMode 效果
- 图片镜像:水平和垂直方向的镜像切换
- 图片 Mipmap:对比开启/关闭 Mipmap 的显示效果
- 动态图播放:播放 GIF 动图,支持暂停控制
3. 代码说明
3.1 图片缩放
文件:Demo_ImageScale.qml
运行效果:
图片缩放展示了如何通过 scale 属性实现图片的缩放效果。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 15 Text { text: "1. 图片缩放" font.pointSize: 13 font.bold: true } Item { Layout.fillWidth: true Layout.fillHeight: true Image { id: image source: "qrc:/images/deepseek-logo.png" width: 100 height: 100 anchors.centerIn: parent property real imageScale: 1.0 scale: imageScale Behavior on imageScale { NumberAnimation { duration: 200 } } } } Slider { Layout.fillWidth: true from: 0.1 to: 3.0 value: 1.0 onValueChanged: image.imageScale = value } } }代码说明:
这是最基础的图片变换操作。通过 Slider 控制 scale 属性,实现平滑的缩放动画效果。
要点:
scale属性控制图片的缩放比例,1.0 为原始大小Behavior on为属性变化添加动画效果NumberAnimation实现数值属性的平滑过渡- 这种用法适合图片查看器、缩略图预览等场景
3.2 图片平移
文件:Demo_ImageTransform.qml
运行效果:
图片平移展示了如何使用 Translate 变换实现拖拽平移效果。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 15 Text { text: "2. 图片平移" font.pointSize: 13 font.bold: true } Item { id: container Layout.fillWidth: true Layout.fillHeight: true Image { id: image source: "qrc:/images/deepseek-logo.png" width: 100 height: 100 anchors.centerIn: parent transform: Translate { id: translateTransform x: 0 y: 0 } } MouseArea { anchors.fill: parent property point lastPos preventStealing: true onPressed: (mouse) => lastPos = Qt.point(mouse.x, mouse.y) onPositionChanged: (mouse) => { var newX = translateTransform.x + mouse.x - lastPos.x var newY = translateTransform.y + mouse.y - lastPos.y var maxX = (container.width - image.width) / 2 var maxY = (container.height - image.height) / 2 var minX = -maxX var minY = -maxY translateTransform.x = Math.max(minX, Math.min(maxX, newX)) translateTransform.y = Math.max(minY, Math.min(maxY, newY)) lastPos = Qt.point(mouse.x, mouse.y) } onWheel: (wheel) => wheel.accepted = true } } Text { Layout.fillWidth: true text: "拖拽图片进行平移" font.pointSize: 10 color: "#666" horizontalAlignment: Text.AlignHCenter } } }代码说明:
通过 MouseArea 捕获鼠标事件,计算位移差并应用到 Translate 变换上,实现拖拽平移效果。
要点:
transform属性接受 Transform 类型的变换对象Translate变换用于实现平移效果preventStealing: true防止鼠标事件被父组件拦截- 通过边界限制确保图片不会移出可视区域
- 这种用法适合图片查看器、地图浏览等场景
3.3 图片旋转
文件:Demo_ImageRotation.qml
运行效果:
图片旋转展示了如何通过 rotation 属性实现旋转效果。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 15 Text { text: "3. 图片旋转" font.pointSize: 13 font.bold: true } Item { Layout.fillWidth: true Layout.fillHeight: true Image { id: image source: "qrc:/images/deepseek-logo.png" width: 100 height: 100 anchors.centerIn: parent property real imageRotation: 0 rotation: imageRotation Behavior on rotation { NumberAnimation { duration: 200 } } } } Slider { Layout.fillWidth: true from: 0 to: 360 value: 0 onValueChanged: image.imageRotation = value } } }代码说明:
通过 rotation 属性控制图片旋转角度,配合 Behavior 实现平滑的旋转动画。
要点:
rotation属性以度为单位,正值为顺时针旋转- 旋转中心默认为图片中心,可通过
transformOrigin修改 Behavior on rotation实现旋转动画效果- 这种用法适合图片编辑器、加载动画等场景
3.4 网络图片加载
文件:Demo_NetworkImage.qml
运行效果:
网络图片加载展示了如何异步加载网络图片并显示加载状态。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: "4. 网络图片加载" font.pointSize: 13 font.bold: true } Image { id: networkImage Layout.fillWidth: true Layout.fillHeight: true source: "https://doc.qt.io/qt-6/images/qtquickcontrols-styles.png" asynchronous: true fillMode: Image.PreserveAspectFit BusyIndicator { anchors.centerIn: parent running: parent.status === Image.Loading } Text { anchors.centerIn: parent visible: parent.status === Image.Error text: "加载失败" color: "red" font.pointSize: 10 } } Text { Layout.fillWidth: true text: networkImage.status === Image.Ready ? "状态: 加载完成" : networkImage.status === Image.Loading ? "状态: 加载中..." : networkImage.status === Image.Error ? "状态: 加载失败" : "状态: 未知" font.pointSize: 10 color: "#666" horizontalAlignment: Text.AlignHCenter } } }代码说明:
通过asynchronous: true启用异步加载,配合status属性显示加载状态。
要点:
asynchronous: true启用异步加载,避免阻塞 UIstatus属性反映图片加载状态:Null / Loading / Ready / ErrorBusyIndicator显示加载中的转圈动画- 根据 status 显示不同的状态提示
- 这种用法适合需要从网络加载图片的应用场景
3.5 图片填充模式
文件:Demo_ImageFillMode.qml
运行效果:
图片填充模式展示了 Image 组件的六种 fillMode 效果。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: "5. 图片填充模式" font.pointSize: 13 font.bold: true } ComboBox { id: fillModeCombo Layout.fillWidth: true model: [ "Stretch - 缩放填充", "PreserveAspectFit - 等比适应", "PreserveAspectCrop - 等比裁剪", "Tile - 平铺", "TileVertically - 垂直平铺", "TileHorizontally - 水平平铺" ] } Item { id: imageContainer Layout.fillWidth: true Layout.fillHeight: true Layout.minimumHeight: 100 clip: true Image { id: fillModeImage source: "qrc:/images/deepseek-logo.png" anchors.fill: parent fillMode: fillModeFromIndex(fillModeCombo.currentIndex) sourceSize: isTileMode(fillModeCombo.currentIndex) ? Qt.size(60, 60) : undefined } } Text { Layout.fillWidth: true text: fillModeDescription(fillModeCombo.currentIndex) font.pointSize: 10 color: "#666" horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap } } function isTileMode(index) { return index === 3 || index === 4 || index === 5 } function fillModeFromIndex(index) { switch(index) { case 0: return Image.Stretch; case 1: return Image.PreserveAspectFit; case 2: return Image.PreserveAspectCrop; case 3: return Image.Tile; case 4: return Image.TileVertically; case 5: return Image.TileHorizontally; default: return Image.Stretch; } } function fillModeDescription(index) { switch(index) { case 0: return "图片拉伸填充整个区域,可能变形"; case 1: return "保持宽高比缩放,图片完整显示,可能有留白"; case 2: return "保持宽高比缩放,填满区域,可能裁剪"; case 3: return "图片以原始大小重复平铺,铺满整个区域"; case 4: return "水平方向缩放,垂直方向以原始大小重复平铺"; case 5: return "垂直方向缩放,水平方向以原始大小重复平铺"; default: return ""; } } }代码说明:
fillMode 属性控制图片如何适应其容器大小,是 Image 组件最常用的属性之一。
填充模式对比:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| Stretch | 拉伸填充,可能变形 | 背景图、占位图 |
| PreserveAspectFit | 等比适应,完整显示 | 缩略图、预览图 |
| PreserveAspectCrop | 等比裁剪,填满区域 | 封面图、头像 |
| Tile | 原始大小平铺 | 纹理背景、图案 |
| TileVertically | 垂直平铺 | 竖条纹背景 |
| TileHorizontally | 水平平铺 | 横条纹背景 |
3.6 图片镜像
文件:Demo_ImageMirror.qml
运行效果:
图片镜像展示了如何实现水平和垂直方向的镜像翻转。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: "6. 图片镜像" font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true Layout.fillHeight: true spacing: 10 Repeater { model: [ { label: "水平镜像", mode: "horizontal" }, { label: "垂直镜像", mode: "vertical" } ] Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: "#f9f9f9" border.color: "#ddd" radius: 4 ColumnLayout { anchors.fill: parent anchors.margins: 6 spacing: 4 Text { text: modelData.label font.pointSize: 9 color: "#555" Layout.alignment: Qt.AlignHCenter } Image { source: "qrc:/images/deepseek-logo.png" Layout.fillWidth: true Layout.fillHeight: true fillMode: Image.PreserveAspectFit mirror: modelData.mode === "horizontal" && mirrorSwitch.checked mirrorVertically: modelData.mode === "vertical" && mirrorVSwitch.checked } } } } } RowLayout { Layout.fillWidth: true spacing: 10 Switch { id: mirrorSwitch text: "水平镜像" } Item { Layout.fillWidth: true } Switch { id: mirrorVSwitch text: "垂直镜像" } } } }代码说明:
通过mirror和mirrorVertically属性实现水平和垂直方向的镜像翻转。
要点:
mirror: true实现水平方向镜像(左右翻转)mirrorVertically: true实现垂直方向镜像(上下翻转)- 两个属性可以独立使用,也可以组合使用
- 这种用法适合图片编辑器、特效处理等场景
3.7 图片 Mipmap
文件:Demo_ImageMipmap.qml
运行效果:
图片 Mipmap 展示了开启和关闭 Mipmap 时的显示效果对比。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: "7. 图片 Mipmap" font.pointSize: 13 font.bold: true } RowLayout { Layout.fillWidth: true Layout.fillHeight: true spacing: 10 Repeater { model: [ { label: "mipmap: false", mipmap: false }, { label: "mipmap: true", mipmap: true } ] Rectangle { Layout.fillWidth: true Layout.fillHeight: true color: "#f9f9f9" border.color: "#ddd" radius: 4 clip: true ColumnLayout { anchors.fill: parent anchors.margins: 6 spacing: 4 Text { text: modelData.label font.pointSize: 9 color: "#555" Layout.alignment: Qt.AlignHCenter } Image { source: "qrc:/images/deepseek-logo.png" Layout.fillWidth: true Layout.fillHeight: true fillMode: Image.PreserveAspectFit mipmap: modelData.mipmap scale: 0.6 } } } } } Text { Layout.fillWidth: true text: "缩小图片时,会降低锯齿感" font.pointSize: 9 color: "#888" horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap } } }代码说明:
Mipmap 是一种纹理映射技术,通过预生成不同分辨率的图片,在缩小显示时获得更好的视觉效果。
要点:
mipmap: true启用 Mipmap 优化- 缩小图片时,Mipmap 可以显著降低锯齿感
- 开启 Mipmap 会略微增加内存占用
- 适合需要频繁缩放的图片显示场景
3.8 动态图播放
文件:Demo_ImageAnimated.qml
运行效果:
动态图播放展示了如何使用 AnimatedImage 组件播放 GIF 动图。
关键代码:
BaseRect { ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 10 Text { text: "8. 动态图" font.pointSize: 13 font.bold: true } Item { Layout.fillWidth: true Layout.fillHeight: true Layout.minimumHeight: 100 AnimatedImage { id: animatedImage source: "qrc:/images/cat.gif" anchors.fill: parent fillMode: Image.PreserveAspectFit paused: pauseSwitch.checked } } RowLayout { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter spacing: 10 Text { text: "帧: " + animatedImage.currentFrame + " / " + animatedImage.frameCount font.pointSize: 10 color: "#333" } Switch { id: pauseSwitch text: "暂停" } } } }代码说明:
AnimatedImage 继承自 Image,专门用于播放 GIF 等动态图片格式。
要点:
AnimatedImage支持 GIF、MNG 等动态图片格式currentFrame获取当前帧索引,frameCount获取总帧数paused属性控制播放/暂停状态playing属性控制是否自动播放(默认 true)- 这种用法适合表情包、加载动画、引导页等场景
4. 技术要点
4.1 Image 属性速查
常用属性:
Image { source: "path/to/image.png" // 图片路径(本地或网络) width: 100 // 宽度 height: 100 // 高度 scale: 1.0 // 缩放比例 rotation: 0 // 旋转角度 opacity: 1.0 // 不透明度 fillMode: Image.PreserveAspectFit // 填充模式 asynchronous: true // 异步加载 mipmap: false // Mipmap 优化 mirror: false // 水平镜像 mirrorVertically: false // 垂直镜像 sourceSize: Qt.size(100, 100) // 源图片尺寸限制 clip: true // 裁剪超出部分 smooth: true // 平滑缩放 }状态属性:
Image { status: Image.Ready // Null / Loading / Ready / Error progress: 0.5 // 加载进度 0.0 ~ 1.0 }4.2 变换类型对比
| 变换类型 | 属性方式 | Transform 方式 | 说明 |
|---|---|---|---|
| 缩放 | scale | Scale | 简单缩放 |
| 旋转 | rotation | Rotation | 简单旋转 |
| 平移 | x, y | Translate | 位置调整 |
| 组合变换 | - | Transform 列表 | 多种变换组合 |
Transform 方式示例:
Image { transform: [ Translate { x: 10; y: 20 }, Rotation { angle: 45 }, Scale { xScale: 1.5; yScale: 1.5 } ] }4.3 Image vs AnimatedImage
| 特性 | Image | AnimatedImage |
|---|---|---|
| 静态图片 | 支持 | 支持 |
| GIF 动图 | 只显示第一帧 | 完整播放 |
| 当前帧 | - | currentFrame |
| 总帧数 | - | frameCount |
| 播放控制 | - | playing / paused |
| 播放速度 | - | speed |
5. 工程下载
下载链接:QML Image 图像组件示例合集