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

Col*_*lin 4 python tkinter ttk python-2.7

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

例如,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()
Run Code Online (Sandbox Code Playgroud)

工作版的截图

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

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()
Run Code Online (Sandbox Code Playgroud)

非工作版本的屏幕截图

tkFont.names()main_frame.pack()列出自定义字体之前的第一个版本中打印出来font<id>,但在第二个版本中打印相同版本不会在define_styles功能外列出自定义字体.我是否必须做一些特殊的事情来拯救他们?

为什么我不能将该代码放在函数中?我是否从根本上误解了字体应该如何使用?tkFont似乎有某种字体注册表,为什么不是我的坚持?

Kev*_*vin 6

我没有证据支持这一点,但我相信你的largeFont对象在Python define_styles结束时被垃圾收集.这是因为没有纯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
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

  • 我认为它处于"bug"和"复杂系统令人惊讶的交互"之间的灰色区域.如果不需要这种手动参考保存,我会喜欢它,但据我所知,开发人员有这样一个很好的理由. (2认同)