检索 tkinter.ttk.Label 小部件的当前字体定义

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

我希望检索当前分配给任意

tkinter.ttk.Label
小部件的字体对象。

(更准确地说,我想获取小部件当前 tkinter.font.Font 实例的确切

配置属性
family
size
weight
slant
underline
overstrike
) - 为了以编程方式定义相同基本字体的修改变体。)

使用简单的、无主题的内容很容易做到这一点

tkinter.Label

import tkinter.font

# Create root object
root = tkinter.Tk()

# Create label widget
label = tkinter.Label( root, text="Hello world!" )
label.pack()

# Get font name (key) from the widget
font_name = label['font']
print( " font_name:", repr(font_name) )

# Get Font instance and print attributes
font = tkinter.font.nametofont( font_name )
for key, value in font.config().items():
    print( f"{key:>10}: {repr(value)}" )

# Display the widget
root.mainloop() 

上面的程序打印出字体详细信息如下:

 font_name: 'TkDefaultFont'
    family: 'sans-serif'
      size: 10
    weight: 'normal'
     slant: 'roman'
 underline: 0
overstrike: 0

但是,如果我将其更改为使用

tkinter.ttk.Label
而不是
tkinter.Label
...

import tkinter.font
import tkinter.ttk

[...]

# Create label widget
label = tkinter.ttk.Label( root, text="Hello world!" )
label.pack()

...它不再起作用了。这是因为表达式

label['font']
现在返回空字符串而不是有效的 Tkinter 字体名称。空字符串被分配给
font_name
,然后在
nametofont
函数调用中使用,结果是:

 font_name: ''
Traceback (most recent call last):
  File "fonttest.py", line 14, in <module>
    font = tkinter.font.nametofont( font_name )
  File "/usr/lib/python3.10/tkinter/font.py", line 23, in nametofont
    return Font(name=name, exists=True, root=root)
  File "/usr/lib/python3.10/tkinter/font.py", line 87, in __init__
    raise tkinter._tkinter.TclError(
_tkinter.TclError: named font font1 does not already exist

如果我进一步更改程序并通过在创建

ttk
对象之后但在创建
root
小部件之前添加以下行来指定命名的
ttk.Label
主题...

# Set up a ttk theme
style = tkinter.ttk.Style()
style.theme_use( 'breeze' )

...我得到了一些不同的结果,但仍然没有有效的字体名称:

 font_name: <font object: 'Helvetica 10'>
Traceback (most recent call last):
  File "fonttest.py", line 20, in <module>
    font = tkinter.font.nametofont( font_name )
  File "/usr/lib/python3.10/tkinter/font.py", line 23, in nametofont
    return Font(name=name, exists=True, root=root)
  File "/usr/lib/python3.10/tkinter/font.py", line 87, in __init__
    raise tkinter._tkinter.TclError(
_tkinter.TclError: named font Helvetica 10 does not already exist

请注意

label['font']
如何不再返回字符串(空字符串或其他字符串),而是返回“字体对象”。


添加更多调试打印...

print( " font_name:", repr(font_name) )
print( "font_name.__class__:", font_name.__class__ )
print( "font_name.__str__():", repr(font_name.__str__()) )
print( "dir( font_name ):", dir( font_name ) )
print( "tkinter.font.names():", tkinter.font.names() ) 

...给我们这个输出:

 font_name: <font object: 'Helvetica 10'>
font_name.__class__: <class '_tkinter.Tcl_Obj'>
font_name.__str__(): 'Helvetica 10'
dir( font_name ): ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'string', 'typename']
tkinter.font.names(): ('TkCaptionFont', 'TkSmallCaptionFont', 'TkTooltipFont', 'TkFixedFont', 'TkHeadingFont', 'TkMenuFont', 'TkIconFont', 'TkTextFont', 'TkDefaultFont')

它并不是真正的“字体名称”,也不是

tkinter.font.Font
的实例,而是
_tkinter.Tcl_Obj
类的实例。
dir
输出列出了一个名为
typename
的成员,所以我也添加了这一行...

print( "font_name.typename:", repr(font_name.typename) )

...产生:

font_name.typename: 'font'

总结一下:有时主题

ttk
小部件为其字体返回空字符串,有时它们返回“字体对象”。 “字体对象”(如果存在)不是 tkinter.font.Font 实例,而是
_tkinter.Tcl_Obj
实例 — 显然是内部 TCL
font
对象的 Python 包装器,其属性无法被 Python 代码访问?
由于这个奇怪的 

font

对象

is
可转换为字符串 (Helvetica 10),因此它可以
技术上
用作字体查找调用中的 Tkinter“字体名称”。唉,该对象保存或转换成的字符串仍然不是注册的“字体名称”(tkinter.font.names()
tkinter.font.nametofont( font_name )
可以识别),因此底层字体的属性仍然无法访问。
所以,我的问题是:以编程方式获取当前 

tkinter.font.Font

实例(或等效属性详细信息 - family

 size
 weight
 slant
 underline
)的
正确
方法是什么,
 overstrike
)在明确设置主题和未设置主题时分配给
tkinter.ttk.Label
小部件的字体?
上面我的测试环境是Python 3.10.12,标配Kubuntu (Ubuntu) 22.04 LTS。软件包 

python3-tk

(版本 3.10.8-1~22.04)和

python3-ttkthemes
(版本 3.2.2+git20220101+07e6509cc6bf-1)是从标准 Ubuntu 存储库手动安装的。
    

python tkinter fonts ttk
1个回答
0
投票
tkinter.font.Font

tkinter.ttk.Style
类 (
tkinter.ttk.Style
) 一起解决您的问题,请参阅下面的代码: import tkinter.font import tkinter.ttk from tkinter.font import BOLD, Font # Create root object root = tkinter.Tk() # Set up a ttk theme stylez = tkinter.ttk.Style() # style.theme_use( 'breeze' ) ### not used see below default_font_root = tkinter.font.nametofont(stylez.lookup(root , 'font')).actual() print('default_font_root : ' , default_font_root) print("default_font_root size : " , default_font_root['size']) # Set up a ttk theme print(stylez.theme_names()) stylez.theme_use(stylez.theme_names()[2]) #same of stylez.theme_use('default') #create Font fontz = Font(root , family = 'Ubuntu', size = 64 , weight = BOLD , underline = 1) stylez.configure('my.TLabel', font = fontz) # Create label widget label = tkinter.ttk.Label(root, text="Hello world!" , style = 'my.TLabel') label.pack() print(""""style.lookup("TLabel", "font" : """ , stylez.lookup("TLabel", "font")) print(""""style.lookup("my.TLabel", "font" : """ , stylez.lookup("my.TLabel", "font")) label_font = tkinter.font.nametofont(stylez.lookup(label['style'] , 'font')).actual() label_font_name = tkinter.font.nametofont(stylez.lookup(label['style'] , 'font')).name print('label_font : ' , label_font, label_font_name) print("fontz['size'] : ", fontz['size']) # Display the widget root.mainloop() """ this is used to get available Font families in your system : from tkinter import Tk, font root = Tk() for i in sorted(font.families()): print('\n',i) """

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