PyQt5托盘图标本地Mac正常显示,客户端Mac无法显示求助
PyQt5系统托盘图标在部分Mac设备不显示的排查方案
我开发了一个PyQt5应用,用于显示系统托盘图标。该图标在我的Mac设备上可正常显示,但在客户端的Mac设备上无法显示(暂无截图)。最初猜测是客户端的托盘图标数量达到上限,但移除一个图标后重新运行应用,问题仍未解决。相关代码如下:
import logging import signal import sys import subprocess import os from PyQt5 import QtGui, QtWidgets, QtCore logger = logging.getLogger(__name__) # This is't used... def refresh(*args): logger.warning('Hello') class Application(QtWidgets.QApplication): def event(self, e): return QtWidgets.QApplication.event(self, e) class Application(QtWidgets.QApplication): def launch_terminal(self): # start backup script cmd = f"cd {os.getcwd()}; env -i PATH=$PATH bash -c ./backup.sh" subprocess.run(['osascript', '-e', f'tell application "Terminal" to do script "{cmd}"']) def check_backup(): if os.path.exists('/tmp/backup_done'): os.remove('/tmp/backup_done') self.quit() # start timer to check if backup is completed self.timer = QtCore.QTimer() self.timer.timeout.connect(check_backup) self.timer.start(1000) # check every second class SystemTrayIcon(QtWidgets.QSystemTrayIcon): def __init__(self, parent=None): super().__init__(parent) self.menu = QtWidgets.QMenu(parent) self.refresh_action = self.menu.addAction("Refresh") self.refresh_action.triggered.connect(refresh) self.exit_action = self.menu.addAction("Exit") self.exit_action.triggered.connect(QtWidgets.qApp.quit) self.setContextMenu(self.menu) # Create a pixmap from a Unicode character font = QtGui.QFont("Arial", 30) pixmap = QtGui.QPixmap(50, 50) pixmap.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(pixmap) painter.setFont(font) painter.drawText(pixmap.rect(), QtCore.Qt.AlignCenter, "🔴") painter.end() self.setIcon(QtGui.QIcon(pixmap)) def main(): app = Application(sys.argv) # Registers a signal handler to exit the application gracefully # when receiving a SIGINT signal (e.g., Ctrl+C on the terminal). signal.signal(signal.SIGINT, lambda *a: app.quit()) tray_icon = SystemTrayIcon() tray_icon.exit_action.triggered.connect(app.quit) tray_icon.show() # Timer calls Application.event repeatedly. app.startTimer(200) app.launch_terminal() sys.exit(app.exec_()) if __name__ == '__main__': main()
可能的原因及解决办法
1. 字体缺失或Unicode渲染兼容性问题
代码中使用Arial字体绘制Unicode emoji图标(🔴),如果客户端Mac未安装Arial字体,或者系统对emoji的渲染机制存在差异,会导致图标无法生成显示。
- 改用系统默认支持的字体,比如
Helvetica,或者直接省略字体参数让系统自动适配:font = QtGui.QFont() - 替换为本地图片文件作为托盘图标,避免动态绘制的兼容性问题:
self.setIcon(QtGui.QIcon("icon.png"))(提前准备好png格式的图标文件)
2. 重复定义Application类导致异常
代码中重复定义了Application类,第一个类仅重写event方法但未被实际使用,这种重复定义可能在不同环境下引发初始化异常。建议合并类的功能:
class Application(QtWidgets.QApplication): def event(self, e): return QtWidgets.QApplication.event(self, e) def launch_terminal(self): # start backup script cmd = f"cd {os.getcwd()}; env -i PATH=$PATH bash -c ./backup.sh" subprocess.run(['osascript', '-e', f'tell application "Terminal" to do script "{cmd}"']) def check_backup(): if os.path.exists('/tmp/backup_done'): os.remove('/tmp/backup_done') self.quit() # start timer to check if backup is completed self.timer = QtCore.QTimer() self.timer.timeout.connect(check_backup) self.timer.start(1000) # check every second
3. Mac系统权限或设置限制
- 检查客户端Mac的系统设置:打开「系统设置」→「通知」,找到该应用并确认允许通知(托盘图标显示可能依赖通知权限)
- 确认托盘图标是否被隐藏:Ventura及以上版本的MacOS会将部分托盘图标收纳到菜单栏右侧的「更多图标」中(点击箭头展开查看)
- 排查是否有安全软件拦截了应用的托盘显示权限
4. 冗余定时器干扰事件循环
代码中调用app.startTimer(200)反复触发event方法,但app.exec_()本身已处理事件循环,该冗余定时器可能干扰托盘图标的初始化流程,建议移除该代码。
5. 动态Pixmap绘制的兼容性问题
动态绘制透明背景的Pixmap可能在部分设备上渲染异常,可以临时修改背景色测试:
pixmap = QtGui.QPixmap(50, 50) pixmap.fill(QtCore.Qt.white) # 替换透明背景为白色测试是否能显示
内容的提问来源于stack exchange,提问作者P i
相关产品推荐
相关产品推荐

