为什么我无法在函数内定义(并保存)Tkinter 字体?

问题描述 投票:0回答:2

在函数内部和脚本主体中定义字体似乎表现不同,我似乎无法弄清楚它应该如何工作。

例如,本例中的

Label
最终采用更大的字体,正如预期的那样:

from Tkinter import *
from ttk import *

import tkFont

root = Tk()

default = tkFont.Font(root=root, name="TkTextFont", exists=True)
large = default.copy()
large.config(size=36)

style = Style(root)
style.configure("Large.TLabel", font=large)

root.title("Font Test")

main_frame = Frame(root)
Label(main_frame, text="Large Font", style="Large.TLabel").pack()

main_frame.pack()
root.mainloop()

Screenshot of working version

但是,如果我尝试在函数内定义样式,似乎字体会被删除或垃圾收集,并且在小部件需要使用它时不可用:

from Tkinter import *
from ttk import *

import tkFont

def define_styles(root):
    default = tkFont.Font(root=root, name="TkTextFont", exists=True)

    large = default.copy()
    large.config(size=36)

    style = Style(root)
    style.configure("Large.TLabel", font=large)


root = Tk()

root.title("Font Test")

define_styles(root)

main_frame = Frame(root)
Label(main_frame, text="Large Font", style="Large.TLabel").grid(row=0, column=0)

main_frame.pack()
root.mainloop()

Screenshot of non-working version

在第一个版本中在

tkFont.names()
之前打印出
main_frame.pack()
会将自定义字体列出为
font<id>
,但在第二个版本中打印相同的内容不会列出
define_styles
函数之外的自定义字体。我需要做一些特别的事情来拯救他们吗?

为什么我不能将该代码放入函数中?我是否从根本上误解了字体的使用方式?

tkFont
似乎有某种字体注册表,为什么我的没有留下来?

python python-2.7 tkinter ttk
2个回答
7
投票

我没有证据支持这一点,但我相信一旦

large
结束,Python 就会对你的
define_styles
Font 对象进行垃圾回收。这是因为没有纯 Python 对象对其有任何引用,即使底层 Tcl 实现仍在使用它。这也是困扰 Tkinter 的
PhotoImage
类的问题。

解决方法是通过对对象进行长期引用来保持对象的活动状态。例如,只需将其分配给

root
对象上的任何旧属性即可。

def define_styles(root):
    default = tkFont.Font(root=root, name="TkTextFont", exists=True)

    large = default.copy()
    large.config(size=36)

    style = Style(root)
    style.configure("Large.TLabel", font=large)
    root.myfont = large

结果:

enter image description here


0
投票

这篇文章是古老的历史,但最近遇到了同样的问题,通过添加

delete_font=False
解决了,如下例所示:

font_default = ttk.font.nametofont('TkDefaultFont')
font_default_config = font_default.actual()
font_default_config['size'] = 12
ttk.font.Font(name='TkDefaultBig', **font_default_config).delete_font = False

不再需要不必要的垃圾收集,字体保留在字典中,并可在其他 GUI 元素中使用。

© www.soinside.com 2019 - 2024. All rights reserved.