一 Image基础
- Image自己是无法显示的他必须依托一个可视化的控件,比如Rectangle
这是最基础的操作。Image 控件最核心的属性就是 source,它告诉 QML 图片在哪里。
支持的格式: PNG(最常用,支持透明)、JPG(照片)、SVG(矢量图,放大不模糊)等。
- 值得注意的是如果加载本地绝对路径的文件需要加上前缀file:///
- 也支持加载网络图片,Qt会自动完成下载并加载
- 如果你不设置
width和height,Image会自动使用图片原本的大小。如果图片很大(比如 1920x1080),它可能会直接撑爆你的窗口!
cpp
import QtQuick
import QtQuick.Window
Window {
width: 400
height: 300
visible: true
Image {
// 1. 写法一:加载本地文件(和代码在同一个文件夹下)
source: "logo.png"
// 2. 写法二:加载网络图片(Qt会自动帮你下载并显示)
// source: "https://www.qt.io/logo.png"
}
}
二 常用属性
| 属性 | 作用 | 常用值/备注 |
|---|---|---|
source |
指定图片路径 | 可以是本地文件,也可以是网址 |
width / height |
设定显示区域大小 | 不写则默认原图大小 |
fillMode |
决定图片怎么适应框 | PreserveAspectFit (保持比例缩放,会有黑白留白) PreserveAspectCrop (裁切,保持图片的长宽比去缩放) Stretch (变形,填满图片不关心比例) |
sourceSize |
限制内存占用 | Qt.size(宽, 高),大图必用! |
asynchronous |
防止卡顿 | true (后台加载) |
smooth |
画面平滑度 | true (默认,抗锯齿) false (有锯齿,像素风) |
三 性能优化(别让程序卡死)
假设你加载了一张 4000x3000 像素 的超高清相机照片,但你只想把它显示在一个 100x100 的小头像框里。
如果不做优化: Qt 会把这张 4000x3000 的大图完整加载到内存里,非常占内存,甚至导致软件崩溃。
做了优化: 告诉 Qt "我只要 100x100 那么大,你加载的时候直接压缩,别把大图弄进来"。
cpp
Image {
width: 100
height: 100
source: "photo.jpg"
// 告诉 Qt:虽然原图很大,但我只要 100x100 的规格就够了。
// Qt 会自动把大图缩小后再加载,极大地节省内存!
sourceSize: Qt.size(100, 100)
}
四:异步加载 (解决卡顿)
如果你加载一张很大的图片,默认情况下,Qt 会暂停界面响应,直到图片加载完才显示。用户会觉得软件"卡了一下"。
解决方法是开启 asynchronous(异步)
cpp
Image {
source: "big_image.png"
asynchronous: true // 让图片在后台悄悄加载,界面不卡顿
}
五 透明度遮罩/不透明度蒙版
OpacityMask是一个**"基于透明度的裁剪工具"**。- 利用
OpacityMask属性,给图片盖上一个'模具'(Mask)。图片(Source)只会透过模具不透明的地方显示出来,从而实现裁剪或异形显示的效果。"
工作原理
你可以把它想象成**"透过形状看世界"**。
想象你在做手工:
- 内容层(被控制者) :这是一张画满图案的画纸(或者你想展示的精美照片)。
- 遮罩层(控制者) :这是一张硬纸板 ,你在中间挖了一个心形的洞。
操作过程:
你把这张挖了心形洞的硬纸板(遮罩层),盖在画纸(内容层)上面。
- 结果:你只能透过那个"心形洞"看到下面的画纸。硬纸板挡住的地方,画纸就被隐藏了。
- 对应原理 :
- 硬纸板的洞 = 透明区域(允许显示)。
- 硬纸板的实体 = 不透明区域(阻挡显示)。
六 实现QQ圆形头像
6.1 准备:通用模具
我们需要一个不可见的"模具"来定义形状。
cpp
Rectangle
{
id: maskShape
width: 120
height: 120
radius: 60 // 正圆
color: "white"
visible: false // 必须隐藏,它只存在于显存中作为遮罩
}
6.2 方法一: 图层特效
核心逻辑 :利用 layer.effect,在图片渲染到屏幕之前,直接在显存中进行"原地加工"。
cpp
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
Window {
width: 400
height: 300
visible: true
color: "#2c3e50"
// 这是一个纯圆形的遮罩模板(不可见,只作为模具)
Rectangle
{
id: maskShape
width: 120
height: 120
radius: 60 // 正圆
color: "white"
visible: false // 必须隐藏,它只存在于显存中作为遮罩
}
// 图片容器
Rectangle {
anchors.centerIn: parent
width: 120
height: 120
color: "#34495e" // 图片没加载出来时的底色
radius: 60
Image {
id: avatar
anchors.fill: parent
source: "file:///C:/Users/18071/Desktop/aaaaaa.png"
fillMode: Image.PreserveAspectCrop
smooth: true
// 【核心魔法】
//开启图层渲染,并强制应用圆形遮罩
layer.enabled: true
layer.smooth: true
// 直接将图片的渲染结果与 maskShape 进行混合
layer.effect: OpacityMask {
source: avatar // 源材料
maskSource: maskShape //
}
}
// 边框(可选)
Rectangle {
anchors.fill: parent
radius: 60
//color: Qt.rgba(0, 0, 0, 0)
color: "#00FFFFFF"
border.color: "white"
border.width: 2
}
}
}
6.3 方法二: 独立控件
OpacityMask作为一个独立的控件,读取 Image的数据。- 设置source: 设置源图片
- 设置makeSource: 设置模具(遮罩)
- 这种方式一定要隐藏原图,因为最终显示的是被OpacityMask处理过之后的图片
cpp
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
Window {
width: 400
height: 300
visible: true
color: "#2c3e50"
// 这是一个纯圆形的遮罩模板(不可见,只作为模具)
Rectangle
{
id: maskShape
width: 120
height: 120
radius: 60 // 正圆
color: "white"
visible: false // 必须隐藏,它只存在于显存中作为遮罩
}
// 图片容器
Rectangle {
anchors.centerIn: parent
width: 120
height: 120
color: "#34495e" // 图片没加载出来时的底色
radius: 60
Image {
id: avatar
anchors.fill: parent
source: "file:///C:/Users/18071/Desktop/aaaaaa.png"
fillMode: Image.PreserveAspectCrop
smooth: true
visible: false
}
OpacityMask
{
anchors.fill: parent
source: avatar // 源材料
maskSource: maskShape //
}
// 边框(可选)
Rectangle {
anchors.fill: parent
radius: 60
//color: Qt.rgba(0, 0, 0, 0)
color: "#00FFFFFF"
border.color: "white"
border.width: 2
}
}
}