如何避免动态生成 tkinter 形式的全局变量?函数插入的值不会保存,手动键入的值会在代码更改后保存



我试图删除我所依赖的全局变量,而不是传递/返回必要的值。它似乎部分起作用,但结果让我感到困惑。

有没有一种方法可以在不切换到面向对象的情况下避免全局变量?*

由于全局变量包含小部件,因此表单可以按需工作。它创建一个默认的空白表单,可以用从文件加载的值重建表单,并保存小部件的值,无论这些值是键入的、从文件加载还是加载后编辑等。

但是,当我尝试传递/返回窗口小部件列表而不是使用全局变量时,只保存手动输入的值,并且一旦调用load_file函数,对save_file的任何调用都只保存手动键入的最后一个值。(若要查看差异,请切换当前注释,对于用内联注释标记的行,则缺少注释(。

我想帮助理解这里的错误,以及正确操作的选项。

import tkinter as tk
root = tk.Tk()
root.geometry('900x800')
form_frame = tk.Frame(root) 
button_frame = tk.Frame(root)
form_frame.grid(row = 0)
button_frame.grid(row = 1)
# default form, or form that matches opened dataset 
def build_form(dataset = None): 
global entry_objects        #<==== Comment out this line (1/4)...
entry_objects = []
if dataset == None:            
rowcount = 2   
else:
rowcount = len(dataset)      
for row_i in range(rowcount):
entry_list = []
if dataset is not None:
data_row = dataset[row_i]     
for col_i in range(3):   
entry = tk.Entry(form_frame)
if dataset is not None:
entry.insert(0, str(data_row[col_i]))
entry_list.append(entry)
entry.grid(row = row_i, column = col_i)    
entry_objects.append(entry_list)
#return(entry_objects)      #<==== ... uncomment this line (2/4)...
def open_file():    # open_file(), save_file() are just substitutes.
test_data = [['a1', 'a2', 'a3'],['b1', 'b2', 'b3'],['c1', 'c2', 'c3']]
build_form(test_data)
def save_file(entry_objects):
entry_values =  [[j.get() for j in i]  for i in entry_objects]
print('--> Saved to csv file: ')
print(entry_values)
build_form()                    #<==== ... comment this line (3/4)...   
#entry_objects = build_form()   #<==== ... and uncomment this line (4/4).   

open_button = tk.Button(button_frame, text = 'Load Test Data',
command = open_file)
save_button = tk.Button(button_frame, text = 'Save', 
command = lambda: save_file(entry_objects))
exit_button = tk.Button(button_frame, 
text = 'Exit', command=root.quit)
open_button.pack(side = 'left')
save_button.pack(side = 'left')
exit_button.pack(side = 'left')
root.mainloop()

这是我的第一个程序中有问题的部分,为了清晰起见,对其进行了大量删减和简化。

*在学习OOP之前,我想澄清一下我在程序方面的困惑。在阅读全局变量引起的问题之前,我使用了它,理解如何避免使用全局变量一直是一个挑战。

关于从动态生成的小部件访问值、避免全局变量等,有很多问题让我走到了这一步,但我不认为这是在解决这个问题。

据我所知,这就是我所能说的。

有了代码(全局entry_object被取消注释(,一切都很好。运行save_file函数时,entry_objects变量将设置为更新后的值,并提供正确的数据。

当build_form函数与return语句一起运行时,open_file函数不会更新为将build_file作为一个值,而是希望它是一个语句。

def open_file():    # this, save_file are just substitutes.
test_data = [['a1', 'a2', 'a3'],['b1', 'b2', 'b3'],['c1', 'c2', 'c3']]
build_form(test_data)    # this does nothing

它应该包括全局语句(因为它正在更改函数外的值(global entry_objects,并且需要将entry_object设置为build_form函数给出的值,即entry_objects = build_form(test_data)。更新后的功能如下:

# updated open_file for when build_form returns a value rather than changing the value by itself
def open_file():
# this makes changes to entry_objects visible to things outside the function
global entry_objects
test_data = [['a1', 'a2', 'a3'],['b1', 'b2', 'b3'],['c1', 'c2', 'c3']]
entry_objects = build_form(test_data)    # this sets the returned value to entry_objects

基本上,我要说的是(在这个混乱的单词中(必须更改entry_object,而进行更改并将更新后的值投影到该变量的所有其他调用的唯一方法是使用global,并使对entry_object的所有更改对其他一切都可见,包括

save_btn = tk.Button(
button_frame, text='Save',
command=lambda: save_file(entry_objects)
).pack(side='left')

最后。

只是一个小提示,试着把你的行包装成74个字符,因为这可以帮助其他使用小屏幕的人看到整个画面,而不是滚动:(

如果我不清楚,请随时告诉我需要解释什么。在这个表格上也做得很好:D

最新更新