tkinter程序使用py2app打包为独立程序后tooltip无法显示如何解决
问题原因
- 坐标计算逻辑错误:你在初始化
ToolTip时就提前获取了根窗口的winfo_x()、winfo_y()坐标,此时根窗口还未完成渲染定位,PyCharm运行时窗口加载速度快,拿到的坐标刚好正确,但py2app打包后的程序启动流程不同,初始化阶段获取到的坐标大多为0,最终tooltip被定位到屏幕可视区域外,无法显示。且你固定保存初始坐标的逻辑也不支持用户拖动窗口后正常显示tooltip。 - py2app打包配置缺失:默认配置没有正确包含tkmacosx依赖,且
argv_emulation参数会和tkinter的无框顶层窗口(wm_overrideredirect创建的tooltip窗口)产生兼容问题,导致窗口不渲染。
解决步骤
1. 修正Tooltip实现代码
去掉初始化时传入固定根坐标的逻辑,每次显示tooltip时动态获取组件实时坐标计算位置,修改后代码如下:
import tkinter as tk from tkmacosx import Button class ToolTip(object): def __init__(self, widget, text, dx=80, dy=55): self.widget = widget self.text = text self.dx = dx # 相对组件的横向偏移 self.dy = dy # 相对组件的纵向偏移 self.tooltipwindow = None def enter(event): self.showTooltip() def leave(event): self.hideTooltip() widget.bind('<Enter>', enter) widget.bind('<Leave>', leave) widget.bind("<ButtonRelease-1>", leave) def showTooltip(self): if self.tooltipwindow: return self.tooltipwindow = tw = tk.Toplevel(self.widget) tw.wm_overrideredirect(1) # 动态计算当前组件的屏幕坐标,加上偏移量 x = self.widget.winfo_rootx() + self.dx y = self.widget.winfo_rooty() + self.dy tw.wm_geometry(f"+{x}+{y}") label = tk.Label(tw, text = self.text, background = "#ffffe0", relief = 'solid', borderwidth = 1) label.pack() def hideTooltip(self): try: if self.tooltipwindow: self.tooltipwindow.destroy() self.tooltipwindow = None except: pass root = tk.Tk() root.title('Start') button = Button(root, text="Quit", command=root.quit) button.pack() # 不需要再传入根窗口初始坐标 ToolTip(widget=button, text="Quits programm", dx=80, dy=55) root.mainloop()
2. 修正py2app打包配置
调整setup.py配置,关闭argv_emulation,显式声明包含tkmacosx依赖,修改后代码如下:
from setuptools import setup APP = ['test.py'] DATA_FILES = [] OPTIONS = { 'argv_emulation': False, 'includes': ['tkmacosx', 'tkinter'] } setup( app=APP, data_files=DATA_FILES, options={'py2app': OPTIONS}, setup_requires=['py2app'], )
3. 重新打包
先删除之前打包生成的build、dist文件夹,再运行打包命令:python setup.py py2app
内容的提问来源于stack exchange,提问作者Mazze
相关产品推荐
相关产品推荐

