当前位置: 首页 > news >正文

在 Qt 中实现变色的图标(tintColor)

响应状态的按钮图标

很多时候,设计要求当按钮的状态变化时(比如 hover、按下,禁用),按钮的背景、文字、图标能够改变颜色,以反馈按钮的当前状态。如下图:

改变文字、背景的颜色很容易,但是改变图标颜色就比较麻烦了。早期的方案,是提供一整套不同颜色图片,分别设置给不同的状态。

比如 iOS 上的 UIButton:

func setImage(UIImage?, for: UIControl.State)
// Sets the image to use for the specified state.

再比如 Android 上的 Drawable selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- pressed -->
    <item android:drawable="@drawable/button_1_selected" android:state_pressed="true"/>
    <!-- focused -->
    <item android:drawable="@drawable/button_1_normal" android:state_focused="true"/>
    <!-- default -->
    <item android:drawable="@drawable/button_1_normal"/>
</selector>

所有一旦要新加或者改变一个图标,都要设计提供一组图片文件,开发一个个的加到代码项目中,再添加一组设置图片的代码,是特别的麻烦。

后来,一些平台提供了相关的解决方案,就是 tintColor。有了 tintColor, 只要一张图片就可以了,通过代码就可以改变图标的颜色。

这里我们主要针对 Qt 框架,对其他平台的 tintColor 有兴趣的话,可以查看下面给出的文档:

Apple Developer Documentation

ImageView  |  Android Developers

给 Qml Image 增加 tintColor

在 Qt 中,目前并不支持 tintColor,所有还需要我们自己造轮子。

不过我们只打算在 Qml 中支持,如果你使用 QWidget,也可以参考我们的思路自己动手实现一个。

先看一下最终给使用者的控件:

import QtQuick 2.12
import QtQuick.Controls 2.5

Image {

    property url originSource
    property string tintColor

    source: {
        if (Qt.colorEqual(tintColor, "transparent"))
            return originSource
        return "image://EffectSync/tint/")
                + encodeURIComponent(originSource)
                + "?tintColor=" + tintColor
    }
}

使用者只需要设置 originSource 和 tintColor 就可以了。

实现 QQuickImageProvider

上面的关键是 "image://" 开头的 url,是通过 ImageProvider 实现的。

如何实现 QQuickImageProvider,在我的另一篇文章中有进过,所以不再重复了。

实现 tintColor 效果

在 QQuickImageProvider 中,拿到原始图片 image 后,我们直接就地修改 image 的像素,将所有颜色,替换为 tintColor 的 r、g、b 值:

    auto size = image.bytesPerLine();
    auto a = tintColor_.alpha();
    auto r = tintColor_.red() * a / 255;
    auto g = tintColor_.green() * a / 255;
    auto b = tintColor_.blue() * a / 255;
    for (int i = 0; i < image.height(); ++i) {
        auto bytes = image.scanLine(i);
        auto end = bytes + size;
        while (bytes < end) {
            if (bytes[3]) {
                a = bytes[3];
                if (a == 255) {
                    bytes[0] = b;
                    bytes[1] = g;
                    bytes[2] = r;
                } else {
                    bytes[0] = b * a / 255;
                    bytes[1] = g * a / 255;
                    bytes[2] = r * a / 255;
                }
            }
            bytes += 4;
        }
    }

注意,QImage 图片的像素一般是 premultiplied ,所以要乘以原始像素的 alpha 值。但是如果原始像素 alpha 为 0,可以不修改改像素,优化性能。

相关文章:

  • MIKE水动力笔记14_数字化海图3之提取任意等深线
  • qml中的一些常用技巧
  • 红黑树,B树、B+树、MySQL索引面试题
  • 基于Vue+Element-ui开发的一个“月日组件”,并发布npm包
  • gRPC RPC技术demo
  • 记录一下ts学习整理的一些知识点
  • java计算机毕业设计基于安卓Android的急救服务APP
  • MyBatis Plus (四) --------- 条件构造器 EntityWrapper
  • 神经网络算法应用案例,神经网络是机器算法吗
  • 2023中国(江西)国际餐饮品牌连锁加盟展览会2月26日开幕
  • Java ServiceLoader、Spring SpringFactoriesLoader、SPI方式解耦第三方组件
  • 聚焦个性化与场景化,全新升级的三星电视看点何在?
  • LeetCode每日一题JAVA、JavaSrcipt题解——2022.08.21-08.31
  • 哪种神经网络最好使用,哪种神经网络最好用
  • 02- Spring IOC与DI
  • 【React系列】如何构建React应用程序
  • css系列之关于字体的事
  • Java Agent 学习笔记
  • JS 面试题总结
  • JS实现简单的MVC模式开发小游戏
  • leetcode386. Lexicographical Numbers
  • Otto开发初探——微服务依赖管理新利器
  • Protobuf3语言指南
  • Swift 中的尾递归和蹦床
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 分享几个不错的工具
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 看域名解析域名安全对SEO的影响
  • 聊聊flink的BlobWriter
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 深入浏览器事件循环的本质
  • 译米田引理
  • hi-nginx-1.3.4编译安装
  • ###STL(标准模板库)
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #if #elif #endif
  • #数学建模# 线性规划问题的Matlab求解
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (编译到47%失败)to be deleted
  • (超详细)语音信号处理之特征提取
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (十八)三元表达式和列表解析
  • (一)Dubbo快速入门、介绍、使用
  • (转)母版页和相对路径
  • .bat批处理(一):@echo off
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET多线程执行函数
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ACM] hdu 1201 18岁生日
  • [AIGC] 使用Curl进行网络请求的常见用法
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配
  • [corCTF 2022] CoRJail: From Null Byte Overflow To Docker Escape