磨砂效果的實現思路
這兩周一直在思考怎么在pyqt上實現窗口磨砂效果,網上搜了一圈,全都是 C++ 的實現方法。正好今天查python的官方文檔的時候看到了 ctypes
里面的 HWND
,想想倒不如換一條思路:讓 C++ 幫我做磨砂的事情,而我只需要在python中調用 dll 中的接口函數就行了。需要注意的是,要想成功調用這個dll必須安好MSVC,不想安的話可以參見《如何在pyqt中通過調用SetWindowCompositionAttribute實現Win10亞克力效果》,這里面用純python的方式實現了窗口磨砂效果。
具體實現流程
-
先寫一個實現磨砂效果的C++函數
setBlur()
,調用的時候只需往這個函數傳遞窗口句柄就行了; -
在VS2019里面把寫好的函數編譯為aeroDll.dll;
-
在python通過
hWnd=ctypes.wintypes.HWND(int(self.winId()))
;把WId類型強制轉換為HWND
類型,接着只需ctypes.cdll.LoadLibrary('Aero\\\aeroDll.dll').setBlur(hWnd)
,就能實現動態鏈接庫的載入和接口函數的調用,源代碼如下:
import sys
from ctypes import cdll
from ctypes.wintypes import HWND
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import QApplication, QWidget
class Demo(QWidget):
""" 磨砂效果的實現 """
def __init__(self):
super().__init__()
self.resize(500, 500)
# 去除邊框
self.setWindowFlags(Qt.FramelessWindowHint)
# 背景透明
self.setAttribute(Qt.WA_TranslucentBackground)
# 設置背景色
self.bgColor = QColor(255,50,50,80) # 可以根據個人需要調節透明度
# 調用api
hWnd = HWND(int(self.winId())) # 直接HWND(self.winId())會報錯
cdll.LoadLibrary('Aero\\aeroDll.dll').setBlur(hWnd) # dll和腳本放在同一個目錄下會報錯找不到dll
def paintEvent(self, e):
""" 繪制背景 """
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
painter.setBrush(self.bgColor)
painter.drawRoundedRect(self.rect(), 20, 20)
if __name__ == "__main__":
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
運行效果如下圖所示(硝子真美(~ ̄▽ ̄)~

源代碼和dll
百度網盤(提取碼:7o6r): link