基本小部件#
本章介绍了您几乎在任何用户界面中都会发现的基本 Tk 小部件:框架、标签、按钮、复选按钮、单选按钮、输入框和组合框。通过本章的学习,您将知道如何使用所有典型的填写表单类型用户界面所需的小部件。
Frame
#
Frame
是显示为简单矩形的小部件。框架有助于组织用户界面,通常在视觉上和编码层面上都有所帮助。框架经常充当几何管理器(如 grid
)的主小部件,该管理器负责管理包含在框架中的从属小部件。
frame = ttk.Frame(parent)
框架可以接受几个不同的配置选项,这些选项可以改变它们的显示方式。
请求的大小#
通常,框架的大小由其中包含的任何小部件的大小和布局决定。反过来,这由管理框架本身的内容的几何管理器控制。
如果出于某种原因,您想要不包含其他小部件的空框架,您可以使用宽度和/或高度配置选项明确设置其大小(否则,您会得到一个非常小的框架)。
屏幕距离如宽度和高度通常以像素数指定。您也可以通过几种后缀之一来指定它们。例如,350 表示 350 像素,350c 表示 350 厘米,350m 表示 350 毫米,350i 表示 350 英寸,350p 表示 350 打印点(1/72 英寸)。
填充#
填充配置选项用于请求小部件内部的额外空间。如果您在框架内放置其他小部件,四周都会有边距。您可以指定所有边的相同填充、不同的水平和垂直填充,或者单独为每一边指定填充。
f['padding'] = 5 # 5 pixels on all sides
f['padding'] = (5,10) # 5 on left and right, 10 on top and bottom
f['padding'] = (5,7,10,12) # left: 5, top: 7, right: 10, bottom: 12
边框#
您可以在框架小部件周围显示边框,以在视觉上将其与周围环境区分开来。您经常会看到这种效果用于使用户界面的一部分看起来凹陷或凸起。为此,您需要设置 borderwidth
配置选项(默认值为 0
,即无边框)和 relief
选项,该选项指定边框的视觉效果。这可以是以下之一:平的(flat
)(默认)、凸起( raised
)、凹陷(sunken
)、实心(solid
)、脊状(ridge
)或槽状(groove
)。
frame['borderwidth'] = 2
frame['relief'] = 'sunken'
更改样式#
框架有样式配置选项,这是所有主题小部件共有的。这让您可以控制它们的许多其他外观或行为方面。这稍微高级一些,所以我们现在不会详细讨论。但这里有一个快速示例,创建一个带有红色背景和凸起边框的“危险”框架。
s = ttk.Style()
s.configure('Danger.TFrame', background='red', borderwidth=5, relief='raised')
ttk.Frame(root, width=200, height=200, style='Danger.TFrame').grid()
Label
#
Label
是显示文本或图像的小部件,通常用户只会查看而不会与之交互。标签用于标识控件或用户界面的其他部分、提供文本反馈或结果等。
label = ttk.Label(parent, text='Full name:')
与 Frame
类似,标签可以接受几个不同的配置选项,这些选项可以改变它们的显示方式。
显示文本#
text
配置选项(如上所示,在创建标签时使用)是最常用的,特别是当标签纯粹是装饰性或解释性的。您可以通过修改这个配置选项来更改显示的文本。这可以在任何时候进行,而不仅仅是在首次创建标签时。
您还可以让小部件监视脚本中的变量。每当变量发生变化时,标签将显示该变量的新值。这是通过 textvariable
选项实现的:
resultsContents = StringVar()
label['textvariable'] = resultsContents
resultsContents.set('New value to display')
Tkinter 只允许您将小部件附加到 StringVar
类的实例上,而不是任意的 Python 变量。这个类包含所有监视变化并在变量与 Tk 之间来回通信的逻辑。使用 get
和 set
方法来读取或写入变量的当前值。
显示图像#
标签还可以显示图像而不是文本。如果您只想在用户界面中显示一个图像,这通常是实现方式。我们将在后面的章节中更详细地讨论图像,但现在让我们假设您想要显示存储在磁盘上的文件中的一个 GIF 图像。这是一个两步的过程。首先,您将创建一个图像“对象”。然后,您可以通过其 image
配置选项告诉标签使用该对象:
image = PhotoImage(file='myimage.gif')
label['image'] = image
标签还可以同时显示图像和文本。您经常会在工具栏按钮中看到这种情况。为此,请使用 compound
配置选项。默认值是 none
,这意味着如果存在图像则仅显示图像;如果没有图像,则显示由 text
或 textvariable
选项指定的文本。compound
选项的其他可能值有 text
(仅文本)、image
(仅图像)、center
(文本在图像中心)、top
(图像在文本上方)、left
、bottom
和 right
。
字体、颜色等#
与框架一样,通常您不希望直接更改字体和颜色等。如果您需要更改它们(例如,创建特殊类型的标签),首选方法是创建一个新的样式,然后通过 style
选项将其应用于小部件。
与大多数主题小部件不同,标签小部件还提供了明确的特定于小部件的配置选项作为替代方案。同样,只有在使用样式不一定有意义的情况下才应使用这些选项。
您可以使用 font
配置选项指定用于显示标签文本的字体。虽然我们将在后面的章节中更详细地讨论字体,但这里列出了一些您可以使用的预定义字体的名称:
TkDefaultFont
: 所有未特别指定的 GUI 项目的默认字体。TkTextFont
: 用于输入小部件、列表框等。TkFixedFont
: 标准的固定宽度字体。TkMenuFont
: 菜单项使用的字体。TkHeadingFont
: 用于列表和表格中列标题的字体。TkCaptionFont
: 窗口和对话框标题栏使用的字体。TkSmallCaptionFont
: 子窗口或工具对话框中使用的较小标题字体。TkIconFont
: 图标标题使用的字体。TkTooltipFont
: 提示信息使用的字体。
label['font'] = "TkDefaultFont"
标签的前景色(文本)和背景色也可以通过 foreground
和 background
配置选项进行更改。颜色将在后续章节详细讨论,但您可以将其指定为颜色名称(例如红色)或十六进制 RGB 代码(例如 #ff340a
)。
标签还接受前面讨论的用于框架的 relief
配置选项,使其看起来凹陷或凸起。
布局#
几何管理器决定了标签的整体布局(即其在用户界面中的位置以及其大小)。然而,有几个选项可以帮助您控制在几何管理器给出的矩形内如何显示标签。
如果给标签的框比标签内容所需的要大,您可以使用 anchor 选项指定标签应该附加到哪个边缘或角落,这将在相对的边缘或角落留下任何空白空间。可能的值以指南针方向指定:n
(北,或顶部边缘),ne
(东北,或右上角),e
,se
,s
,sw
,w
,nw
或 center
。
多行标签#
标签可以显示多行文本。为此,可以在 text
(或 textvariable
)字符串中嵌入换行符(\n
)。标签还可以通过 wraplength
选项自动将文本折成多行,该选项指定一行的最大长度(以像素、厘米等为单位)。
备注
多行标签是经典 Tk 中旧版 message
小部件的替代品。
您还可以通过 justify
选项控制文本的对齐方式。它可以取值为 left
、center
或 right
。如果您只有单行文本,可能需要使用 anchor
选项。
Entry
#
一个输入小部件为用户提供了单行文本字段,他们可以在这里输入字符串值。这些值可以是各种内容,比如名字、城市、密码、社会保险号等。
username = StringVar()
name = ttk.Entry(parent, textvariable=username)
可以指定 width
度配置选项,以确定条目应占据的字符数。例如,这允许您为邮政编码或邮递区号显示较短的条目。
Entry
内容#
已经知道,单选按钮和复选框控件都有与之关联的值。输入框也是如此,这个值通常通过 textvariable
配置选项指定的链接变量来访问。
与各种按钮不同,输入框旁边没有文本或图像来标识它们。为此可以使用单独的标签控件。
你也可以不通过链接变量来获取或更改输入框的值。get()
方法返回当前值,而 delete()
和 insert()
方法允许你更改内容,例如:
print(f'current value is {name.get()}')
name.delete(0,'end') # 删除两个索引之间的内容,基于0的索引
name.insert(0, 'your name') # 在给定索引处插入新文本
监测变化#
输入小部件没有提供 command
选项来在每次输入发生变化时调用回调函数。为了监测变化,你应该监视关联变量的变化。
def it_has_been_written(*args):
...
username.trace_add("write", it_has_been_written)
如果你使用 stick
如上所示的简单 trace_add
用法,你将没有问题。你可能想知道这是观察变量并在它们被读取、写入或删除时触发回调的更复杂系统中的很小的部分。你可以触发多个回调,添加或删除它们(trace_remove
),并对它们进行内省(trace_info
)。
备注
这些方法还取代了现已废弃的旧方法集(trace
, trace_variable
, trace_vdelete
和 trace_vinfo
),这些旧方法不应该再被使用。
Tkinter 允许你监测 StringVar
(或 Variable
的任何子类)上的变化。新旧追踪工具都是对 Tcl 的 trace
命令非常薄(且不太符合 Python 风格)的前端接口。
验证#
用户可以通过输入框输入任何文本。然而,如果您希望限制他们可以输入的内容,可以使用验证功能来实现。例如,输入框可能只接受整数或有效的邮政编码。
您的程序可以指定什么使输入有效或无效,以及何时检查其有效性。正如我们很快将看到的,这两者是相关的。我们将从简单的例子开始,一个只能容纳最多五位数字的整数输入框。
验证标准通过输入框的 validatecommand
配置选项来指定。您提供代码片段,其作用是验证输入内容。它的作用类似于小部件回调或事件绑定,只是它返回值(输入是否有效)。将在每次按键时验证输入;这是通过在 validate
配置选项中提供 key
值来实现的。
import re
def check_num(newval):
return re.match('^[0-9]*$', newval) is not None and len(newval) <= 5
check_num_wrapper = (root.register(check_num), '%P')
num = StringVar()
e = ttk.Entry(root, textvariable=num, validate='key', validatecommand=check_num_wrapper)
e.grid(column=0, row=0, sticky='we')
有几件事值得注意。首先,与事件绑定一样,我们可以通过百分号替换访问触发验证的条件的更多信息。在这里使用了其中一个:%P
是如果验证通过,输入的新值。我们将使用简单的正则表达式和长度检查来确定更改是否有效。要拒绝更改,我们的验证命令可以返回假值,使输入保持不变。
利用这些百分号替换需要一些技巧。您会记得,Tkinter 在事件绑定回调中抽象了百分号替换。所有事件参数都被包装成传递给回调的事件对象。验证回调没有等效的抽象。相反,我们必须选择我们对哪些百分号替换感兴趣。register
方法(可以调用任何小部件,不仅仅是 root
)创建 Tcl 过程,它将调用我们的 Python 函数。我们选择的百分号替换将作为参数传递给它。
让我们扩展我们的例子,使输入框接受美国邮政编码,格式为 "#####"
或 "#####-####"
(#
可以是任何数字)。我们仍然会在每次按键时进行一些验证(只允许输入数字或连字符)。然而,我们不能在每次按键时完全验证输入;如果他们刚刚输入第一个数字,它就还不有效。因此,完全验证只有在输入失去焦点时才会发生(例如,用户离开它时)。Tk 将这种重新验证称为重新验证,与预验证(每次按键都接受更改)相对。
我们应该如何响应错误?让我们添加一条消息提醒用户格式。如果他们输入错误的键或在输入不包含有效邮政编码时离开输入框,消息将出现。当他们返回到输入框或输入有效键时,我们将移除消息。我们还将添加一个(虚拟)按钮来“处理”邮政编码,该按钮将在邮政编码无效时禁用。最后,我们还将添加“姓名”输入框,这样您就可以从邮政编码输入框中切换。
import re
errmsg = StringVar()
formatmsg = "Zip should be ##### or #####-####"
def check_zip(newval, op):
errmsg.set('')
valid = re.match('^[0-9]{5}(\\-[0-9]{4})?$', newval) is not None
btn.state(['!disabled'] if valid else ['disabled'])
if op=='key':
ok_so_far = re.match('^[0-9\\-]*$', newval) is not None and len(newval) <= 10
if not ok_so_far:
errmsg.set(formatmsg)
return ok_so_far
elif op=='focusout':
if not valid:
errmsg.set(formatmsg)
return valid
check_zip_wrapper = (root.register(check_zip), '%P', '%V')
zip = StringVar()
f = ttk.Frame(root)
f.grid(column=0, row=0)
ttk.Label(f, text='Name:').grid(column=0, row=0, padx=5, pady=5)
ttk.Entry(f).grid(column=1, row=0, padx=5, pady=5)
ttk.Label(f, text='Zip:').grid(column=0, row=1, padx=5, pady=5)
e = ttk.Entry(f, textvariable=zip, validate='all', validatecommand=check_zip_wrapper)
e.grid(column=1, row=1, padx=5, pady=5)
btn = ttk.Button(f, text="Process")
btn.grid(column=2, row=1, padx=5, pady=5)
btn.state(['disabled'])
msg = ttk.Label(f, font='TkSmallCaptionFont', foreground='red', textvariable=errmsg)
msg.grid(column=1, row=2, padx=5, pady=5, sticky='w')
请注意,validate
配置选项已从 key
更改为 all
。这意味着 validatecommand
回调不仅会在按键时被调用,还会在其他触发器上被调用。触发器通过 %V
百分号替换传递给回调函数。回调函数可以区分 key
和焦点失去(focusout
)触发器(您也可以检查焦点获得,即 focusin
)。
小技巧
关于验证还有一些其他需要注意的事项。首先,如果您的 validatecommand
生成错误(或不返回布尔值),那么该小部件的验证将被禁用。您的回调可以修改输入内容,例如,更改其 textvariable
属性。您可以随时通过调用其 validate
方法来要求小部件进行验证,如果验证通过,该方法将返回 true
(%V
百分比替换设置为 forced
)。
还有 invalidcommand
配置选项(其工作方式类似于 validatecommand
),每当验证失败时都会被调用。您可以使用它来完成一些棘手的事情,比如强制将焦点重新定位到未通过验证的小部件上。实际上,很少使用它。如前所述,输入框的无效状态标志(可以通过 instate
invalid
方法检查)会在验证成功或失败时自动更新。
其他的百分比替换允许您获取编辑前的输入框内容(%s
)、区分插入和删除(%d
)、插入或删除发生的位置(%i
)、正在插入或删除的内容(%S
)、当前 validate
选项的设置(%v
)和小部件的名称(%W
)。
示例:密码#
Entry可用于密码,其中实际内容显示为项目符号或其他符号。 为此,将 "show"
配置选项设置为要显示的字符,例如 “*”。
下面直接看一个例子:
from tkinter import ttk, Tk, StringVar
if __name__ == '__main__':
root = Tk() # 主窗口
root.title('Entry 测试')
root.geometry('400x300') # 设定窗口大小
user_name = StringVar() # 记录用户名称
user_name.set('Tom')
# 设置字符个数不得超过 7
name = ttk.Entry(root, textvariable=user_name, width=7) # root 上的 Entry 小部件
name.pack()
# 隐藏名称
hide_name = ttk.Entry(root, textvariable=user_name, show=' ')
hide_name.pack()
# 隐藏为 *
hide_name1 = ttk.Entry(root, textvariable=user_name, show='*')
hide_name1.pack()
root.mainloop()
显示结果为:
示例:验证输入内容的合法性的#
我们需要利用 ttk.Entry
的 'validate'
与 'validatecommand'
选项,检查输入的文本是否合法,具体的步骤是:
定义一个负责检查输入内容的回调函数,如果合法则返回
True
,否则返回False
;使用
ttk.Entry
的方法register
将回调函数封装为 Tcl,它会返回一个字符串,用它来设定'validatecommand'
选项;设置
'validate'
,声明调用回调函数的时机,常用的选项有:'focus'
:输入框获取或者失去焦点时'focusin'
:输入框获取焦点时'focusin'
:输入框失去焦点时'key'
:内容改变时'all'
:以上任何情况发生时'none'
:关闭内容检查,这是默认值
具体的选项描述见下表:
选项 |
描述 |
---|---|
‘validate’ |
该选项设置是否启用内容验证 |
‘invalidcommand’ |
1. 指定当输入框输入的内容“非法”时调用的函数;2. 也就是指定当 |
‘validatecommand’ |
1. 该选项指定一个验证函数,用于验证输入框内容是否合法;2. 验证函数需要返回 |
比如,下面的代码验证输入内容是否为 “Python”:
class Window(Tk):
def __init__(self):
super().__init__()
self.in_var = StringVar() # 输入变量
self.out_var = StringVar() # 输出变量
self.input_entry = ttk.Entry(textvariable=self.in_var)
self.input_entry['validate'] = "focusout"
self.input_entry['validatecommand'] = self.test
# 测试 self.input_entry 光标 离开之后的验证
self.show_entry = ttk.Entry(textvariable=self.out_var)
self._layout()
def test(self):
'''验证输入内容是否为 Python'''
if self.input_entry.get() == 'Python':
self.out_var.set('输入正确')
return True
else:
self.out_var.set('输入错误')
return False
def _layout(self):
self.input_entry.grid()
self.show_entry.grid()
window = Window()
window.mainloop()
添加如下两个设置:
self.input_entry['invalidcommand'] = self.test2
def test2(self):
self.show_entry.insert('end', " 我被调用了......")
return True
便可在验证 'invalidcommand'
的使用情况。
示例:使用注册机制验证输入内容的合法性的#
我们也可以使用注册机制验证输入内容的合法性的。即使用配置选项 validatecommand=(register_func, s1, s2, ...)
,其中 register_func
为验证函数名,s1
、s2
这些是额外的选项,这些选项会作为参数依次传给 register_func
函数。下表列出额外的选项的描述:
额外选项 |
含义 |
---|---|
‘%d’ |
操作代码:0 表示删除操作;1 表示插入操作;2 表示获得、失去焦点或 ‘textvariable’ 变量的值被修改 |
‘%i’ |
1. 当用户尝试插入或删除操作的时候,该选线表示插入或删除的位置(索引号);2. 如果是由于获得、失去焦点或 ‘textvariable’ 变量的值被修改而调用验证函数,那么该值是 -1 |
‘%P’ |
1. 当输入框的值允许改变的时候,该值有效;2. 该值为输入框的最新文本内容 |
‘%s’ |
该值为调用验证函数前输入框的文本内容 |
‘%S’ |
1. 当插入或删除操作触发验证函数的时候,该值有效;2. 该选项表示文本被插入和删除的内容 |
‘%v’ |
该组件当前的 ‘validate’ 选项的值 |
‘%V’ |
1. 调用验证函数的原因;2. 该值是 ‘focusin’,‘focusout’,‘key’ 或 ‘forced’(‘textvariable’ 选项指定的变量值被修改)中的一个 |
‘%W’ |
该组件的名字 |
下面看一个例子:
class Window(Tk):
def __init__(self):
super().__init__()
self.in_var = StringVar() # 输入变量
self.out_var = StringVar() # 输出变量
self.input_entry = ttk.Entry(textvariable=self.in_var)
self.input_entry['validate'] = "focusout"
self.test_cmd= self.register(self.test) # 注册
self.input_entry['validatecommand'] = (self.test_cmd, '%P', '%v', '%W')
# 测试 self.input_entry 光标 离开之后的验证
self.show_label = ttk.Label(textvariable=self.out_var)
self._layout()
def test(self, content, reason, name):
'''验证输入内容是否为 Python'''
if content == 'Python':
str1 = '输入正确\n'
str1 += f"{content}, {reason}, {name}"
self.out_var.set(str1)
return True
else:
str1 = '输入错误\n'
str1 += f"{content}, {reason}, {name}"
self.out_var.set(str1)
return False
def _layout(self):
self.input_entry.grid()
self.show_label.grid()
window = Window()
window.mainloop()
显示效果:
您也可以使用类的重写功能修改验证内容,比如:
class ValidatingEntry(Entry):
# base class for validating entry widgets
def __init__(self, master, value="", **kw):
apply(Entry.__init__, (self, master), kw)
self.__value = value
self.__variable = StringVar()
self.__variable.set(value)
self.__variable.trace("w", self.__callback)
self.config(textvariable=self.__variable)
def __callback(self, *dummy):
value = self.__variable.get()
newvalue = self.validate(value)
if newvalue is None:
self.__variable.set(self.__value)
elif newvalue != value:
self.__value = newvalue
self.__variable.set(self.newvalue)
else:
self.__value = value
def validate(self, value):
# override: return value, new value, or None if invalid
return value
Combobox
#
组合框小部件将输入框和选项列表结合起来。这使得用户既可以从你提供的一组值中选择(例如,常见设置),也可以输入自己的值(例如,针对不常见的情况)。
countryvar = StringVar()
country = ttk.Combobox(parent, textvariable=countryvar)
与条目类似,textvariable
选项将程序中的变量与组合框的当前值链接起来。与其他小部件一样,您应该在自己的代码中初始化链接的变量。
组合框会产生 <<ComboboxSelected>>
虚拟事件,每当其值发生变化时,您可以绑定到此事件。(正如我们在之前讨论的几个小部件中所看到的,您还可以追踪 textvariable
的变化。由于直接绑定到事件更为直接,因此这通常是我们的首选方法。)
country.bind('<<ComboboxSelected>>', function)
预定义值#
您可以使用 values
配置选项提供一个用户可选择的值列表:
country['values'] = ('USA', 'Canada', 'Australia')
如果设置了 readonly
状态标志,用户将只能从预定义的值列表中进行选择,但不能输入自己的值(尽管如果组合框的当前值不在列表中,它也不会改变)。
country.state(["readonly"])
备注
如果您在只读模式下使用组合框,我建议当值发生变化时(即在 <<ComboboxSelected>>
事件上),调用 selection_clear
方法。如果不这样做,视觉上会显得有些奇怪。
您还可以使用 get
方法获取当前值,并使用 set
方法更改当前值(该方法接受一个参数,即新值)。
为了补充 get
和 set
方法,您还可以使用 current
方法来确定选中的是预定义值列表中的哪个项目。调用 current
时不带任何参数;它将返回列表中的基于 0
的索引,或者如果当前值不在列表中,则返回 -1
。您可以通过传递基于 0
的索引参数来选择列表中的项。
示例#
您可以使用 "current"
方法来确定在预定义值列表中选择了哪个项目。比如:
root = Tk()
root.geometry('200x100')
label_top = ttk.Label(root, text = "选择您最喜欢的水果")
label_top.grid(column=0, row=0)
fruits = ["香蕉", '苹果', '西瓜', '葡萄', '樱桃']
combo = ttk.Combobox(root, values=fruits)
combo.grid(column=0, row=1)
combo.current(2) # 设定默认选项
root.mainloop()
显示结果为:
如果设置 ttk.Combobox 的状态为 "readonly"
(即combo['state'] = "readonly"
),则无法直接修改选项的值。
"<ComboboxSelected>"
#
可以使用 ttk.Combobox 的 get()
获取其当前的取值,使用 set
方法设定新的值。ttk.Combobox 会生成 "<ComboboxSelected>"
虚拟事件,提供 bind
函数使用。比如,添加如下设定:
out_var = StringVar()
out_label = ttk.Label(root, textvariable=out_var)
out_label.grid(column=0, row=2)
def callback_func(event):
index = combo.current() # 获取当前索引
value = combo.get() # 获取当前的值
out_var.set(f"索引 是 {index}, 选择的值是 {value}")
combo.bind("<<ComboboxSelected>>", callback_func)
这样每次您选择一个选项时,便会触发虚拟事件,效果见下图:
示例:创建英尺转换为米的工具#
代码:
from tkinter import ttk, Tk, StringVar
from tkinter import N, W, E, S
class App(ttk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.feet = StringVar()
self.meters = StringVar()
self._layout()
for child in self.winfo_children():
child.grid_configure(padx=5, pady=5)
@property
def widgets(self):
_widgets = [
[ttk.Entry(self, width=14, textvariable=self.feet),
ttk.Label(self, text="feet")],
[ttk.Label(self, text="is equivalent to"),
ttk.Label(self, textvariable=self.meters),
ttk.Label(self, text="meters")],
[ttk.Button(self, text="Calculate", command=self.calculate)]
]
return _widgets
def grid_layout(self):
for n_row, row in enumerate(self.widgets):
for n_col, widget in enumerate(row):
widget.grid(column=n_col, row=n_row, sticky=(E, W))
def _layout(self):
# 设定 master 的 Resize
self.master.columnconfigure(0, weight=1)
self.master.rowconfigure(0, weight=1)
self['padding'] = 3, 3, 12, 12
self.grid(column=0, row=0, sticky=(N, W, E, S))
self.grid_layout()
def calculate(self, *args):
try:
value = float(self.feet.get())
self.meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
root = Tk()
root.title('Feet to Meters')
app = App(master=root)
app.mainloop()
显示结果为:
为了支持 <Enter>
(键盘回车)键盘触发事件,可以这样:
class App1(App):
def __init__(self, master=None):
super().__init__(master)
self.widgets[0][0].focus()
self.master.bind('<Return>', self.calculate)
# 键盘触发事件
root = Tk()
root.title('Feet to Meters')
app = App1(master=root)
app.mainloop()
如果想要为 ttk.Frame
添加统一的配置,可以这样:
class App(ttk.Frame):
def __init__(self):
super().__init__()
self.option_add("*Font", "arial 40 bold") # 添加统一的字体设定