在Mac OS上设置tkinter图标

9

我正在尝试更改出现在我的Tk应用程序上的图标,以适用于Mac OS。上次我检查时,这段代码适用于Windows。目标是使此解决方案适用于所有平台。

root = tk.Tk()
app = Application(master=root)

app.master.iconbitmap("my_icon.ico")

app.mainloop()

这段代码添加了一个默认的图标来表示.pdf文件,但这不是我想要的。路径到my_icon.ico是正确的。为什么在Mac OS上不起作用?是否有一种跨平台的终极解决方案?

5个回答

8
根据tk tcl文档,你可以尝试使用wm iconphoto。它似乎支持OSX,并建议将文件设置为512x512以实现在MAC上的平滑渲染。
我没有MAC,所以无法测试,但你可以试试看,然后告诉我是否有帮助。
更新:
正如@l'L'l指出的那样,你可能需要尝试root.iconphoto(True, img)。由于我没有Mac,因此无法进行测试。
import tkinter as tk

root = tk.Tk()
img = tk.Image("photo", file="icon.gif")
# root.iconphoto(True, img) # you may also want to try this.
root.tk.call('wm','iconphoto', root._w, img)

root.mainloop()

以下是来自文档的相关文本:

wm iconphoto window ?-default? image1 ?image2 ...? 基于指定的命名图片为窗口设置标题栏图标。如果指定了-default,则此操作也适用于所有未来创建的顶层窗口。图片中的数据在调用时被视为快照。如果稍后更改了图片,则标题栏上的图标不会反映这些更改。允许接受多个图片以提供不同的图片大小(例如16x16和32x32)。窗口管理器可能会将提供的图标缩放到适当的大小。在Windows上,这些图像打包成Windows图标结构。这将覆盖通过wm iconbitmap指定的ico文件,反之亦然。

在X上,这些图像被排列成_NET_WM_ICON X属性,大多数现代窗口管理器支持。wm iconbitmap可以同时存在。建议使用不超过2个图标,首先放置较大的图标。

在Macintosh上,第一个被调用的图像将被加载到OSX本机图标格式中,并成为对话框、Dock和其他上下文中的应用程序图标。在脚本级别,该命令将只接受传递参数的第一个图像,因为macOS上支持多种大小/分辨率是Tk范围之外的功能。开发人员应使用他们可以支持的最大图标(最好为512像素),以确保在Mac上平滑呈现。

我已在Windows上进行了测试,以确保它至少可以在那里工作。我使用了蓝色正方形图像进行测试。

如果以上文档准确,则它也应该在MAC上工作。

enter image description here


_tkinter.TclError: 无法识别图像文件“icon.ico”的数据。我认为问题在于文件类型“.ico”,而不是将文件添加到tkinter的方法。 - Jake
@Jake 我没有使用 .ico 文件。ico 只适用于 Windows。Linux 也有自己的文件类型。尝试使用 gif 文件,看看效果如何。 - Mike - SMT
@Jake 对于这种方法,实际上并没有使用图标文件。这就是为什么 gif 在这里起作用的原因。因此,gif 应该在所有系统上都可以使用。 - Mike - SMT
1
实际上,这种(古老的)技术似乎不适用于 macOS(它使用 X11 作为窗口管理器)。更改此类窗口的 title 属性足够简单,但是在 Mac 上,窗口始终使用默认的 X11 图标,而不管 tkinter 是否指向图标。顺便说一下,您应该只需调用 root.iconphoto(True, img) 而不是调用 tk 来设置图标... - l'L'l
@Mike-SMT,你所描述的方法在某种程度上是有效的。图标出现在码头上并且看起来很好。然而,在标题附近没有出现图标。我今晚会尝试@l'L'l的建议。是否有一个特定的扩展名用于x11图标,或者只是icon.x11 - Jake
显示剩余4条评论

4
如果您使用的是Mac OS,则需要使用.icns图像而不是.ico图像。
您可以使用:
from tkinter import Tk
from platform import system

platformD = system()
if platformD == 'Darwin':

    logo_image = 'images/logo.icns'

elif platformD == 'Windows':

    logo_image = 'images/logo.ico'

else:

    logo_image = 'images/logo.xbm'

root = Tk()
root.title("My App")
root.iconbitmap(logo_image)
root.resizable(0, 0)
root.mainloop()


2

我找到了一个解决方法,通过使用pyobjc模块来更改应用程序图标而不是窗口图标。

import tkinter as tk
import sys

root = tk.Tk()

if sys.platform.startswith('darwin'):
    try:
        from Cocoa import NSApplication, NSImage
    except ImportError:
        print('Unable to import pyobjc modules')
    else:
        ns_application = NSApplication.sharedApplication()
        logo_ns_image = NSImage.alloc().initByReferencingFile_('/path/to/icon.icns')
        ns_application.setApplicationIconImage_(logo_ns_image)
else:
    pass # handle other platforms

root.mainloop()

除了tkinter之外,也适用于其他GUI,例如pywebview。 - ecp

1
重要提示:这种方法比实际任务需要的工作量要长很多。但是,它确实带来了一些无关的好处。请注意,可能有更好的方法,但这个方法也可以。
总之,继续......

你可以使用py2app

Py2app会将您的程序转换为一个.app,这意味着它以应用程序的形式运行(因为它就是应用程序)。当使用tkinter时,这通常是您最终想要的,因为GUI通常被转换为应用程序以方便使用。您可以阅读py2app文档here,或者阅读一个非官方但更易于理解(我个人认为)的教程here。我还会总结如何进行此过程。

首先安装py2app: 在命令提示符中输入以下内容:

sudo pip install -U py2app

如果成功,您应该得到py2app。 如果不成功,可能的一个问题是您没有pip。您可以使用另一个命令下载它:
sudo easy_install pip

步骤一: 在与程序相同的目录中创建名为setup.py的文件。
步骤二: 将此内容放入文件中。
from setuptools import setup

#APP would be the name of the file your code is in.
APP = ['example.py']
DATA_FILES = []
#The Magic is in OPTIONS.
OPTIONS = {
    'argv_emulation': False,
    'iconfile': 'app.icns', #change app.icns to the image file name!!!
    }

setup(
    app=APP,
    name='Your app’s name', #change to anything
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

步骤3: 然后在文件所在的目录中打开bash终端,并输入以下命令:

python setup.py py2app -A

-A参数使应用程序能够响应代码更新,但也会使应用程序无法共享。当你完成开发后,重新运行命令,这次不需要使用-A参数,就像这样:

python setup.py py2app

注意:对于 Python 3 的 py2app,您可能需要使用命令 python3 setup.py py2... 而不是 python setup.py py2...
步骤4: 导航到包含您的代码的字典 dist。在该文件夹中将会有您的应用程序。(当您运行命令时,在第三步中应该已经创建了dist 文件夹)
对于 Windows 用户:不应使用 py2app,而应使用 py2exe

我不认为这会解决图标未出现的原始问题。 - Jake
这将创建自己的图标,移除tkinter默认图标。我忘记指定如何更改py2app默认图像,现在正在编辑... - Eb946207
请查看编辑后的答案。抱歉我忘记包含更改图像。 ;) 更改在第二步中,即带有'iconfile': 'app.icns'的部分。 - Eb946207
这是一个独立应用的解决方案。OP只想在从IDE执行代码时更改窗口左上角的图标。 - Mike - SMT
@Mike - SMT 确实,但是一个独立的应用程序,大多数tkinter程序最终都会变成这样,它有自己的标志。这将创建一个独立的应用程序,但它也将解决他的问题,即设置图标。虽然它的副作用可能不是最好的答案,但这些副作用可能仍然有帮助。而且这个答案仍然有效。 - Eb946207
经过一番查找,我可能已经找到了一些不需要转换为EXE就能运行的解决方案。可悲的是,我没有先在Mac上测试的能力。 - Mike - SMT

0

tkinter.iconbitmap 在 Mac 上创建一个代理图标,它是指向该文件的快捷方式。如果你右键单击一个文件并选择 获取信息,弹出的窗口会显示一个图标,这就是该文件的图标。你可以拖动该图标,这将移动该文件。这就是代理图标。如果你使用一个 .app 文件设置了 iconbitmap,那么代理图标将是该应用程序的图标。由于从应用程序文件夹拖出的文件会创建快捷方式,如果你将 iconbitmap 设置为一个 .app,那么如果你拖动标题栏的图标,它将创建一个快捷方式。这很有帮助,因为你不希望用户能够轻易地将你的图标文件拖出其目录,这样下次加载你的 tkinter 程序时,它就无法正常工作了。enter image description here 在将你的 tkinter 程序转换为应用程序之前,添加 root.iconbitmap("/Applications/<appname>.app")。然后将你的应用程序移动到应用程序文件夹中。当你打开你的应用程序时,你的 tkinter 窗口将具有你的应用程序的图标。如果你将该图标拖到另一个文件夹中,它将创建一个指向你的应用程序的快捷方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接