Files
shuidrop_gui/windows_taskbar_fix.py

167 lines
6.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Windows任务栏图标修复模块
解决PyQt5应用在任务栏显示Python图标的问题
"""
import os
import sys
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import QSize
def get_resource_path(relative_path):
"""获取资源文件的绝对路径兼容开发环境和PyInstaller打包环境"""
try:
# PyInstaller打包后的环境
if getattr(sys, 'frozen', False):
# 获取可执行文件目录
exe_dir = os.path.dirname(sys.executable)
# 检查新版PyInstaller的_internal目录结构
internal_dir = os.path.join(exe_dir, "_internal")
if os.path.exists(internal_dir):
# 新版PyInstaller: exe在外面资源在_internal里
base_path = internal_dir
print(f"[INFO] 检测到PyInstaller _internal 结构: {internal_dir}")
else:
# 老版PyInstaller或onefile模式
if hasattr(sys, '_MEIPASS'):
# 一次性临时解压目录
base_path = sys._MEIPASS
print(f"[INFO] 使用PyInstaller临时解压目录: {base_path}")
else:
# 直接exe目录
base_path = exe_dir
print(f"[INFO] 使用exe目录: {base_path}")
else:
# 开发环境:需要智能判断项目根目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 检查当前目录是否包含static文件夹即为项目根目录
if os.path.exists(os.path.join(script_dir, "static")):
base_path = script_dir
print(f"[INFO] 开发环境基础路径(当前目录): {base_path}")
else:
# 如果当前目录没有static尝试上级目录
parent_dir = os.path.dirname(script_dir)
if os.path.exists(os.path.join(parent_dir, "static")):
base_path = parent_dir
print(f"[INFO] 开发环境基础路径(上级目录): {base_path}")
else:
# 如果都找不到,默认使用当前目录
base_path = script_dir
print(f"[INFO] 开发环境基础路径(默认当前): {base_path}")
# 组合完整路径
full_path = os.path.join(base_path, relative_path)
print(f"[INFO] 资源路径: {relative_path} -> {full_path}")
return full_path
except Exception as e:
print(f"[ERROR] 获取资源路径失败: {e}")
return relative_path
def set_windows_app_id(app_id="ShuidropAI.CustomerService.1.0"):
"""设置Windows应用程序用户模型ID"""
try:
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(app_id)
print(f"[INFO] Windows应用ID已设置: {app_id}")
return True
except Exception as e:
print(f"[WARNING] 设置Windows应用ID失败: {e}")
return False
def create_multi_size_icon():
"""创建包含多种尺寸的QIcon对象"""
try:
icon = QIcon()
# 我们有的图标文件
available_files = [
("static/ai_assistant_icon_16.png", 16),
("static/ai_assistant_icon_32.png", 32),
("static/ai_assistant_icon_64.png", 64),
]
icon_loaded = False
for relative_path, size in available_files:
icon_path = get_resource_path(relative_path)
if os.path.exists(icon_path):
icon.addFile(icon_path, QSize(size, size))
print(f"[INFO] 添加图标 {size}x{size}: {os.path.basename(icon_path)}")
icon_loaded = True
else:
print(f"[WARNING] 图标文件不存在: {icon_path}")
# 如果没有加载任何图标,尝试加载单个文件
if not icon_loaded:
fallback_path = get_resource_path("static/ai_assistant_icon_32.png")
if os.path.exists(fallback_path):
icon = QIcon(fallback_path)
print(f"[INFO] 使用备用图标: {fallback_path}")
icon_loaded = True
if not icon_loaded:
print("[WARNING] 没有找到任何图标文件,将使用系统默认图标")
return icon
except Exception as e:
print(f"[ERROR] 创建多尺寸图标失败: {e}")
return QIcon()
def setup_windows_taskbar_icon(app, window=None):
"""完整设置Windows任务栏图标"""
print("[INFO] 开始设置Windows任务栏图标...")
# 1. 设置应用程序唯一ID
set_windows_app_id()
# 2. 创建多尺寸图标
icon = create_multi_size_icon()
# 3. 设置应用程序级别图标
app.setWindowIcon(icon)
print("[INFO] 应用程序图标已设置")
# 4. 如果提供了窗口,也设置窗口图标
if window:
window.setWindowIcon(icon)
print("[INFO] 窗口图标已设置")
# 5. 强制刷新应用程序图标缓存
try:
if window and hasattr(window, 'winId'):
# 等待窗口完全初始化
from PyQt5.QtCore import QTimer
def delayed_icon_refresh():
try:
window.setWindowIcon(icon)
print("[INFO] 已延迟刷新窗口图标")
except Exception as e:
print(f"[WARNING] 延迟图标刷新失败: {e}")
# 延迟100ms再次设置图标
QTimer.singleShot(100, delayed_icon_refresh)
except Exception as e:
print(f"[WARNING] 图标刷新失败: {e}")
print("[INFO] Windows任务栏图标设置完成")
return icon
if __name__ == "__main__":
# 测试模块
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
app = QApplication(sys.argv)
window = QMainWindow()
window.setWindowTitle("任务栏图标测试")
window.setCentralWidget(QLabel("测试Windows任务栏图标"))
# 设置任务栏图标
setup_windows_taskbar_icon(app, window)
window.show()
sys.exit(app.exec_())