前言

Windows10 在 UWP 应用中支持亚克力画刷,可以在部件的底部绘制亚克力效果的背景图。下面我们使用 QLabel 来模拟这个磨砂过程。

实现方法

MSDN 文档中介绍了亚克力材料的配方,包括:高斯模糊、亮度混合、色调混合和噪声纹理。

高斯模糊

我们先来实现高斯模糊的效果,使用 scipy 可以很轻松的实现这个过程:

# coding:utf-8
import numpy as np
from PIL import Image
from PyQt5.QtGui import QPixmap
from scipy.ndimage.filters import gaussian_filter def gaussianBlur(imagePath: str, blurRadius=18, brightFactor=1, blurPicSize: tuple = None) -> np.ndarray:
""" 对图片进行高斯模糊处理 Parameters
----------
imagePath: str
图片路径 blurRadius: int
模糊半径 brightFactor:float
亮度缩放因子 blurPicSize: tuple
高斯模糊前将图片缩放到指定大小,可以加快模糊速度 Returns
-------
image: `~np.ndarray` of shape `(w, h, c)`
高斯模糊后的图像
"""
if not imagePath.startswith(':'):
image = Image.open(imagePath)
else:
image = Image.fromqpixmap(QPixmap(imagePath)) if blurPicSize:
# 调整图片尺寸,减小计算量,还能增加额外的模糊
w, h = image.size
ratio = min(blurPicSize[0] / w, blurPicSize[1] / h)
w_, h_ = w * ratio, h * ratio if w_ < w:
image = image.resize((int(w_), int(h_)), Image.ANTIALIAS) image = np.array(image) # 处理图像是灰度图的情况
if len(image.shape) == 2:
image = np.stack([image, image, image], axis=-1) # 对每一个颜色通道分别磨砂
for i in range(3):
image[:, :, i] = gaussian_filter(
image[:, :, i], blurRadius) * brightFactor return image

亚克力纹理

接下来在 QLabel 上面绘制出亮度混合、色调混合和噪声纹理,一般色调混合使用的颜色是图像的主题色,可以用 colorthief 库提取,这里就不赘述了:

class AcrylicTextureLabel(QLabel):
""" 亚克力纹理标签 """ def __init__(self, tintColor: QColor, luminosityColor: QColor, noiseOpacity=0.03, parent=None):
"""
Parameters
----------
tintColor: QColor
RGB 主色调 luminosityColor: QColor
亮度层颜色 noiseOpacity: float
噪声层透明度 parent:
父级窗口
"""
super().__init__(parent=parent)
self.tintColor = QColor(tintColor)
self.luminosityColor = QColor(luminosityColor)
self.noiseOpacity = noiseOpacity
self.noiseImage = QImage('resource/noise.png')
self.setAttribute(Qt.WA_TranslucentBackground) def setTintColor(self, color: QColor):
""" 设置主色调 """
self.tintColor = color
self.update() def paintEvent(self, e):
""" 绘制亚克力纹理 """
acrylicTexture = QImage(64, 64, QImage.Format_ARGB32_Premultiplied) # 绘制亮度层
acrylicTexture.fill(self.luminosityColor) # 绘制主色调
painter = QPainter(acrylicTexture)
painter.fillRect(acrylicTexture.rect(), self.tintColor) # 绘制噪声
painter.setOpacity(self.noiseOpacity)
painter.drawImage(acrylicTexture.rect(), self.noiseImage) acrylicBrush = QBrush(acrylicTexture)
painter = QPainter(self)
painter.fillRect(self.rect(), acrylicBrush)

用到的噪声图像如下图所示:

亚克力标签

最后在 QLabel 上叠加磨砂图像和亚克力纹理,可以通过 Image.toqpixmap()Image 转换为 QPixmap

class AcrylicLabel(QLabel):
""" 亚克力标签 """ def __init__(self, blurRadius: int, tintColor: QColor, luminosityColor=QColor(255, 255, 255, 0),
maxBlurSize: tuple = None, parent=None):
"""
Parameters
----------
blurRadius: int
磨砂半径 tintColor: QColor
主色调 luminosityColor: QColor
亮度层颜色 maxBlurSize: tuple
最大磨砂尺寸,越小磨砂速度越快 parent:
父级窗口
"""
super().__init__(parent=parent)
self.imagePath = ''
self.blurPixmap = QPixmap()
self.blurRadius = blurRadius
self.maxBlurSize = maxBlurSize
self.acrylicTextureLabel = AcrylicTextureLabel(
tintColor, luminosityColor, parent=self) def setImage(self, imagePath: str):
""" 设置图片 """
if imagePath == self.imagePath:
return self.imagePath = imagePath
image = Image.fromarray(gaussianBlur(
imagePath, self.blurRadius, 0.85, self.maxBlurSize))
self.blurPixmap = image.toqpixmap() # type:QPixmap
self.setPixmap(self.blurPixmap)
self.adjustSize() def setTintColor(self, color: QColor):
""" 设置主色调 """
self.acrylicTextureLabel.setTintColor(color) def resizeEvent(self, e):
super().resizeEvent(e)
self.acrylicTextureLabel.resize(self.size())
self.setPixmap(self.blurPixmap.scaled(
self.size(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation))

测试

下面是测试用的埃罗芒阿老师:

代码如下:

# coding:utf-8
import sys from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QApplication from acrylic import AcrylicLabel app = QApplication(sys.argv)
w = AcrylicLabel(20, QColor(105, 114, 168, 102))
w.setImage('resource/ClariS_ヒトリゴト (アニメ盤).jpg')
w.show()
app.exec_()

结果如下:

如何在pyqt中实现亚克力磨砂效果的QLabel的更多相关文章

  1. 如何在pyqt中实现窗口磨砂效果

    磨砂效果的实现思路 这两周一直在思考怎么在pyqt上实现窗口磨砂效果,网上搜了一圈,全都是 C++ 的实现方法.正好今天查python的官方文档的时候看到了 ctypes 里面的 HWND,想想倒不如 ...

  2. 如何在pyqt中实现win10亚克力效果

    亚克力效果的实现思路 上一篇博客<如何在pyqt中实现窗口磨砂效果> 中实现了win7中的Aero效果,但是和win10的亚克力效果相比,Aero还是差了点内味.所以今天早上又在网上搜了一 ...

  3. 如何在pyqt中通过调用 SetWindowCompositionAttribute 实现Win10亚克力效果

    亚克力效果 在<如何在pyqt中实现窗口磨砂效果>和<如何在pyqt中实现win10亚克力效果>中,我们调用C++ dll来实现窗口效果,这种方法要求电脑上必须装有MSVC.V ...

  4. 如何在pyqt中自定义无边框窗口

    前言 之前写过很多关于无边框窗口并给窗口添加特效的博客,按照时间线罗列如下: 如何在pyqt中实现窗口磨砂效果 如何在pyqt中实现win10亚克力效果 如何在pyqt中通过调用SetWindowCo ...

  5. 如何在pyqt中实现带动画的动态QMenu

    弹出菜单的视觉效果 QLineEdit 原生的菜单弹出效果十分生硬,而且样式很丑.所以照着Groove中单行输入框弹出菜单的样式和动画效果写了一个可以实现动态变化Item的弹出菜单,根据剪贴板的内容是 ...

  6. 如何在pyqt中在实现无边框窗口的同时保留Windows窗口动画效果(一)

    无边框窗体的实现思路 在pyqt中只要 self.setWindowFlags(Qt.FramelessWindowHint) 就可以实现边框的去除,但是没了标题栏也意味着窗口大小无法改变.窗口无法拖 ...

  7. 如何在pyqt中给无边框窗口添加DWM环绕阴影

    前言 在之前的博客<如何在pyqt中通过调用SetWindowCompositionAttribute实现Win10亚克力效果>中,我们实现了窗口的亚克力效果,同时也用SetWindowC ...

  8. 如何在 pyqt 中捕获并处理 Alt+F4 快捷键

    前言 如果在 Windows 系统的任意一个窗口中按下 Alt+F4,默认行为是关闭窗口(或者最小化到托盘).对于使用了亚克力效果的窗口,使用 Alt+F4 最小化到托盘,再次弹出窗口的时候可能出现亚 ...

  9. 如何在pyqt中使用 QGraphicsView 实现图片查看器

    前言 在 PyQt 中可以使用很多方式实现照片查看器,最朴素的做法就是重写 QWidget 的 paintEvent().mouseMoveEvent 等事件,但是如果要在图像上多添加一些形状,那么在 ...

随机推荐

  1. spoj - ACTIV - Activities

    ACTIV - Activities Ana likes many activities. She likes acrobatics, alchemy, archery, art, Arabic da ...

  2. Travelling(hdu3001)

    Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. Sky Code(poj3904)

    Sky Code Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2085   Accepted: 665 Descripti ...

  4. MADE: Masked Autoencoder for Distribution Estimation

    目录 概 主要内容 代码 Germain M., Gregor K., Murray I. and Larochelle H. MADE: Masked Autoencoder for Distrib ...

  5. 使用所学Spring知识,实现简易的图书查询系统功能。实现查询全部图书。 根据书籍编号查询信息。 根据书名查询书籍信息。 根据状态查询书籍信息。

    相关 知识 >>> 相关 练习 >>> 实现要求: 使用所学Spring知识,实现简易的图书查询系统功能. 要求如下: 查询全部图书. 根据书籍编号查询信息. 根据 ...

  6. SpringCloud创建Config Client配置读取

    1.说明 本文详细介绍配置中心客户端使用方法, 即Config Client到Config Server读取配置, 这里以创建Config Client服务为例, 基于已经创建好的Config Ser ...

  7. JZOJ5966. [NOIP2018TGD2T3] 保卫王国 (动态DP做法)

    题目大意 这还不是人尽皆知? 有一棵树, 每个节点放军队的代价是\(a_i\), 一条边连接的两个点至少有一个要放军队, 还有\(q\)次询问, 每次规定其中的两个一定需要/不可放置军队, 问这样修改 ...

  8. mysql语句3-插入、修改删除表

    二.DML数据操纵语句 关键字:insert(插入)  delete(删除)  update(更新)  select(查询) 1.表创建好以后,就可以插入记录了,语法如下: 方法一 :insert i ...

  9. java同时替换多个字符串

    参考资料: https://blog.csdn.net/qq_39390545/article/details/106020221 来自为知笔记(Wiz)

  10. react中prop-types的使用

    什么是prop-types?prop代表父组件传递过来的值,types代表类型.简单来说就是用来校验父组件传递过来值的类型 import PropTypes from 'prop-types'; To ...