从系统终端运行时QSystemTrayIcon设置的尺寸未生效但VSCode终端正常
根因分析
- 终端环境变量差异:VSCode内嵌终端启动时会自动注入Qt高分屏适配相关的环境变量,原生Bash终端默认无此类变量,导致Qt的缩放逻辑执行结果不一致。
- 代码未适配多缩放场景:创建QPixmap时硬编码像素尺寸,未结合当前屏幕的设备像素比动态调整,也未固定文本渲染的字体参数,不同缩放比例下文本显示尺寸会出现偏差。
- 属性生效兼容性问题:部分PyQt5版本中,通过类方法提前设置应用属性存在不生效的概率,需配合环境变量强制指定适配规则。
修复方案
- 代码入口处强制设置Qt高分屏适配环境变量,屏蔽不同终端的环境差异
- 生成图标前获取当前屏幕的设备像素比,动态计算Pixmap的物理像素尺寸
- 主动固定绘图字体大小,保证文本渲染尺寸一致
- 为Pixmap设置对应设备像素比,让Qt自动适配托盘图标显示要求
修复后完整代码
import sys import os from PyQt5.QtWidgets import * from PyQt5 import QtCore, QtWidgets, QtGui, QtSvg # 强制配置Qt高分屏适配环境变量,屏蔽终端环境差异 os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" os.environ["QT_SCREEN_SCALE_FACTORS"] = "" os.environ["QT_SCALE_FACTOR"] = "" def create_tray_icon(label): r"""Creates QIcon with the given label.""" # 托盘图标逻辑尺寸,可根据需求调整 logic_w, logic_h = 88, 22 # 获取当前屏幕设备像素比 screen = QApplication.primaryScreen() dpr = screen.devicePixelRatio() # 计算适配高分屏的物理像素尺寸 pix_w, pix_h = int(logic_w * dpr), int(logic_h * dpr) pixmap = QtGui.QPixmap(pix_w, pix_h) pixmap.setDevicePixelRatio(dpr) pixmap.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(pixmap) # 固定字体尺寸,避免系统默认字体差异影响显示效果 font = painter.font() font.setPixelSize(int(14 * dpr)) painter.setFont(font) painter.setPen(QtGui.QColor("white")) align = int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) painter.drawText(pixmap.rect(), align, str(label)) painter.end() icon = QtGui.QIcon() icon.addPixmap(pixmap) return icon class SystemTrayIcon(QtWidgets.QSystemTrayIcon): def __init__(self, icon, parent=None): QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) self.menu = QtWidgets.QMenu(parent) exitAction = self.menu.addAction("Exit") exitAction.triggered.connect(lambda: sys.exit()) self.setContextMenu(self.menu) def memprofilerApp(): r"""Runs the Qt Application.""" QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps) app = QApplication(sys.argv) icon = create_tray_icon(label="Hello world!") trayIcon = SystemTrayIcon(icon) trayIcon.show() sys.exit(app.exec_()) if __name__ == '__main__': memprofilerApp()
内容的提问来源于stack exchange,提问作者Blademaster。
相关产品推荐
相关产品推荐

