[QML] QML IMage图像处理

一 Image基础

  • Image自己是无法显示的他必须依托一个可视化的控件,比如Rectangle

这是最基础的操作。Image 控件最核心的属性就是 source,它告诉 QML 图片在哪里。

支持的格式: PNG(最常用,支持透明)、JPG(照片)、SVG(矢量图,放大不模糊)等。

  • 值得注意的是如果加载本地绝对路径的文件需要加上前缀file:///
  • 也支持加载网络图片,Qt会自动完成下载并加载
  • 如果你不设置 widthheightImage自动使用图片原本的大小。如果图片很大(比如 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 方法二: 独立控件

  1. OpacityMask 作为一个独立的控件,读取 Image的数据。
  2. 设置source: 设置源图片
  3. 设置makeSource: 设置模具(遮罩)
  4. 这种方式一定要隐藏原图,因为最终显示的是被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
        }
    }
}
相关推荐
AI_Claude_code2 小时前
ZLibrary访问困境方案四:利用Cloudflare Workers等边缘计算实现访问
javascript·人工智能·爬虫·python·网络爬虫·边缘计算·爬山算法
AwesomeCPA2 小时前
Miaoduo MCP 使用指南(VDI内网环境)
前端·ui·ai编程
前端大波2 小时前
前端面试通关包(2026版,完整版)
前端·面试·职场和发展
qq_433502182 小时前
Codex cli 飞书文档创建进阶实用命令 + Skill 创建&使用 小白完整教程
java·前端·飞书
IT_陈寒2 小时前
为什么我的Vite热更新老是重新加载整个页面?
前端·人工智能·后端
还在忙碌的吴小二2 小时前
Harness 最佳实践:Java Spring Boot 项目落地 OpenSpec + Claude Code
java·开发语言·spring boot·后端·spring
liliangcsdn2 小时前
mstsc不在“C:\Windows\System32“下在C:\windows\WinSxS\anmd64xxx“问题分析
开发语言·windows