83 lines
3.3 KiB
Python
83 lines
3.3 KiB
Python
# coding: utf-8
|
||
"""主题切换回归自检(无窗口, 离屏渲染)。
|
||
|
||
背景: fluent 控件直接 setStyleSheet 的样式会在 setTheme 时被库重刷的自带 qss 冲掉
|
||
(v0.4.0 RGB swatch 按钮切主题丢底色的根因)。swatch 改走 setCustomStyleSheet、
|
||
标题字号走 QFont 后,本测试保证:
|
||
1. Dark -> Light -> Dark -> Light 往返后 9 个 swatch 按钮样式表仍带底色;
|
||
2. Light 下实际渲染出的按钮中心像素 = swatch 色值(不只样式表字符串存在);
|
||
3. 标题 24px 加粗(QFont)在往返后不变。
|
||
|
||
运行: python selftest_theme.py (依赖 PySide6-Fluent-Widgets)
|
||
"""
|
||
import os
|
||
import sys
|
||
|
||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
|
||
from PySide6.QtGui import QColor
|
||
from PySide6.QtWidgets import QApplication
|
||
from qfluentwidgets import PushButton, StrongBodyLabel, Theme, setTheme
|
||
|
||
import app_fluent
|
||
import patterns
|
||
|
||
|
||
def check_style_sheet(win, app):
|
||
swatches = [b for b in win.findChildren(PushButton) if b.text() in {"55", "AA", "FF"}]
|
||
assert len(swatches) == 9, f"expect 9 swatch buttons, got {len(swatches)}"
|
||
title = [l for l in win.findChildren(StrongBodyLabel) if l.text() == "DLPilot"]
|
||
assert len(title) == 1, "title label not found"
|
||
colored = sum(1 for b in swatches if "background-color: #" in b.styleSheet())
|
||
f = title[0].font()
|
||
print(f" swatch 样式表带底色: {colored}/9, 标题 24px 粗体: "
|
||
f"{f.pixelSize() == 24 and f.bold()}")
|
||
return colored == 9 and f.pixelSize() == 24 and f.bold()
|
||
|
||
|
||
def check_rendered_pixel(win, app):
|
||
"""Light 主题下逐个渲染 swatch,与目标色一致的像素须占明显多数(背景为主,
|
||
中心处是文字字形,不能只采单点)。"""
|
||
ok = True
|
||
for channel, items in patterns.SOLID_ROWS:
|
||
for label, color in items:
|
||
button = next(b for b in win.findChildren(PushButton)
|
||
if b.text() == label and f"background-color: {color}" in b.styleSheet())
|
||
image = button.grab().toImage()
|
||
target = QColor(color)
|
||
total, matched = image.width() * image.height(), 0
|
||
for y in range(image.height()):
|
||
for x in range(image.width()):
|
||
if image.pixelColor(x, y) == target:
|
||
matched += 1
|
||
ratio = matched / total
|
||
same = ratio >= 0.2
|
||
ok &= same
|
||
if not same:
|
||
print(f" 渲染不符: {channel}/{label} 期望 {color} 仅占 {ratio:.0%}")
|
||
print(f" Light 下渲染像素比对: {'一致' if ok else '存在偏差'}")
|
||
return ok
|
||
|
||
|
||
def main():
|
||
app = QApplication.instance() or QApplication(sys.argv)
|
||
setTheme(Theme.AUTO)
|
||
win = app_fluent.App(0)
|
||
passed = True
|
||
for step, theme in (("初始 Dark", Theme.DARK), ("切 Light", Theme.LIGHT),
|
||
("切回 Dark", Theme.DARK), ("再切 Light", Theme.LIGHT)):
|
||
setTheme(theme)
|
||
app.processEvents()
|
||
print(f"[{step}]")
|
||
passed &= check_style_sheet(win, app)
|
||
if theme == Theme.LIGHT:
|
||
passed &= check_rendered_pixel(win, app)
|
||
win.close()
|
||
print("ALL PASS" if passed else "FAILED")
|
||
return 0 if passed else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|