python - 在 Dialog 的 body 方法中创建 StringVar 时不保持其初始值
问题描述
我看到使用 a 的行为tk.StringVar
是DiaLog
我没想到的。我的问题是为什么 GUI 会以这种方式运行,或者我做了什么让它以这种方式运行。我可以通过使用类属性而不是变量来修复它。
在以下两种情况下,StringVar
都以 的body
方法开头Dialog
。
在第一个示例中,class AsExpected
将 StringVar 分配给var
初始化为“Test”的类属性。在打开对话框时,条目按预期显示“测试”。输入到条目中的任何内容都会回显到标签,链接到相同的 StringVar。
在第二个示例中,class Unexpected
将 StringVar 分配给方法中的局部变量。打开对话框时,条目是空白的,链接到同一 StringVar 的标签也是空白。输入到条目中的任何内容仍会回显到标签,因此从小部件到 StringVar 的链接仍然保持不变,但初始化文本会丢失。
从实验来看,行为与变量的范围有关。使其全局化会给出预期的行为,并将其包含在任何形式的闭包中,除了body
,会给出预期的行为。我不明白为什么 StringVar 仍然链接到条目和标签,但在过程中的某处被重置为空白。
我也尝试过使用顶级窗口。行为与对话框相同。如果将 StringVar 分配给局部变量,则初始文本将丢失。如果它是全局的或闭包的一部分,则保留初始文本。在创建后使用 set 设置 StringVar 的行为方式相同。
下面的示例旨在使它们保持简单。简单的解决方法是使用属性作为 StringVar 的参考,但我很好奇发生了什么导致这种行为在 Linux、Windows 10 和 Mac OS tk/tcl 版本 8.6 上测试。或者我在做什么来导致这种行为?
这表现得如我所料。
import tkinter as tk
from tkinter import ttk
from tkinter import simpledialog
class AsExpected( simpledialog.Dialog ):
""" This exhibits the behaviour I'd expect. The initialisation text in the StringVar
shows in the Entry and Label widgets when the dialog opens.
"""
def body( self, parent ):
ttk.Label( parent, text = "The Entry opens with the initial 'Test' text and anything" ).grid()
ttk.Label( parent, text = "typed into the Entry still echoes to the Label." ).grid()
self.var = tk.StringVar( parent, value = 'Test' ) # var is an attribute of AsExpected
ent = ttk.Entry( parent, textvariable = self.var )
ent.grid( pady = 5 )
ttk.Label( parent, textvariable = self.var ).grid( pady = 5 )
return ent
def apply( self ):
""" Sets result to a dict after 'Ok' is clicked. """
self.result = { 'ans': self.var.get() }
# Create an application to trigger the dialog.
root = tk.Tk()
root.title( 'Test' )
choice = 0
def choose():
global choice
choice = AsExpected( root, 'As Expected' )
print( choice.result )
ttk. Label( root, text = "This version keeps the initial value in the StringVar." ).grid( padx = 10, pady = 10 )
ttk.Button( root, text = 'Click to open dialogue.', command = choose ).grid( pady = 5 )
root.mainloop()
这将在对话框打开时将条目和标签留空。
import tkinter as tk
from tkinter import ttk
from tkinter import simpledialog
class Unexpected( simpledialog.Dialog ):
""" This exhibits the behaviour I didn't expect. The initialisation text in the StringVar
doesn't show in the Entry and Label widgets when the dialog opens.
"""
def body( self, parent ):
def ontrace( *args ):
# Used to test using trace and the button command if the Button or trace code is uncommented.
print( var, var.get() )
ttk.Label( parent, text = "The Entry with blank not with the initial 'Test' text." ).grid()
ttk.Label( parent, text = "but anything typed into the Entry still echoes to the Label." ).grid()
var = tk.StringVar( self, value = 'Test', name = 'body_var' ) # var is a variable in body.
ent = ttk.Entry( parent, textvariable = var )
ent.grid( pady = 5 )
ttk.Label( parent, textvariable = var ).grid( pady = 5 )
print( var, var.get() )
# Uncommenting any of the 3 statements below shows the initial value as the dialogue opens.
# ttk.Button( parent, text = 'Print StringVar', command = ontrace ).grid()
# var.trace( 'w', ontrace )
# self.fetch = lambda: var.get()
return ent
def fetch( self ):
return 'OK Clicked'
def apply( self ):
""" Sets result to a dict after 'Ok' is clicked. """
self.result = { 'ans': self.fetch() }
root = tk.Tk()
root.title( 'Test' )
choice = 0
def choose():
global choice
choice = Unexpected( root, 'Unexpected behaviour' )
print( choice.result )
ttk. Label( root, text = "This version doesn't keep the initial value in the StringVar." ).grid( padx = 10, pady = 10 )
ttk.Button( root, text = 'Click to open dialogue.', command = choose ).grid( pady = 5 )
root.mainloop()
解决方案
推荐阅读
- java - 从不确定的数量中找到所有可能的组合
- python - 获得数字总和的最有效方法是什么?
- angular - Angular 9 - 不是已知元素
- java - 如何在主机 Maven 中配置以重用其存储库内容,以供 LAN 参考?(没有罐子的副本)
- javascript - 过滤通过 Nivo 条形图的数据
- python-3.x - 我不明白为什么在我的代码中使用 "" 有效,但带有 ' ' 的相同代码不起作用
- r - 清理数据 - 将数据框中的一列扩展到多列
- python - 与目录和包一起使用的 Python 导入
- python - 通过“to_excel”插入数据框会覆盖文件的其余部分
- java - 我正在解决 PRIME GENERATOR 的 SPOJ 问题 2。作为 SPOJ 编译器的输出,我得到了错误的答案。有人能帮我吗?