我正在使用GUI来使用Python 2.7中的Tkinter和ttk自动化项目管道的一部分。我有一个主Tk()窗口,在单击“自动检测”时生成Toplevel()窗口,然后根据代码中其他位置定义的分子种类列表,在按钮单击时创建一系列动态的只读Entry小部件。
我的问题是,虽然Entry框确实根据检测到的物种正确显示,但一旦创建它们的函数终止,它们就不会保留物种名称。我怀疑这是因为小部件不是全局的[甚至在Tk()窗口的范围内],而是仅在函数内定义。但是,我无法在定义Tk()窗口的代码块中创建它们,因为在按下按钮之前所需的Entry框数是未知的(因此调用创建它们的函数)。
我在下面包含了一个抽象的代码块,它显示了我遇到的问题。道歉,如果它很长。我试图尽可能地减少它。我在代码中包含的评论显示了我对正在发生的事情的想法和猜测。它应该准备好在Python 2.7中运行;我希望唯一需要的Python 3.x更改是导入修改。
我的问题是,在我在主Tk()窗口调用的函数中动态创建Entry小部件并用文本填充它们之后,如何防止它们在函数结束时减少填充?免责声明:我不是一个程序员(甚至在计算机科学领域),所以我会尽我所能来坚持所有技术细节,但我可能不得不问一些愚蠢的问题。
from Tkinter import *
import ttk
from time import sleep
def update_list(manager, rows):
species_list = ['A','B','C','D']
del rows[1:]
for widget in manager.children.values():
widget.grid_forget()
if not species_list == ['']:
species_elem_list = []
for i, each in enumerate(species_list):
## Here I attempt to create a dynamic list of StringVars to attach to the Entry fields below, based on the contents of the species list.
species_elem_list.append(StringVar())
## Here I initialize the values of the elements of the Entry fields by setting the StringVar of each.
species_elem_list[i].set(each)
## I tried to attach the value of the StringVar (from the species list) to the Entry below, but when the program is run, the Entry does not stay populated.
temp_name = ttk.Entry(manager, textvariable=species_elem_list[i], state='readonly')
temp_color = ttk.Label(manager, text='data')
temp_row = [temp_name, temp_color]
rows.append(temp_row)
for row_number in range(len(rows)):
for column_number, each in enumerate(rows[row_number]):
each.grid(column=column_number, row=row_number)
each.grid()
manager.update()
sleep(3) ## Included so that the population of the fields can be observed before they depopulate.
## After this point, the update_list function terminates.
## When that happens, the Entry fields depopulate. How can I get them to persist after the function terminates?
root = Tk()
manager = ttk.Frame(root, padding='4 5 4 4')
manager.grid(column=0, row=0, sticky=NSEW)
name_label = ttk.Label(manager, text='Name')
color_label = ttk.Label(manager, text='RGB')
rows = [[name_label, color_label]]
options = ttk.Frame(root)
options.grid(sticky=NSEW)
detect_button = ttk.Button(options, text='Auto-Detect', command=lambda: update_list(manager,rows))
done_button = ttk.Button(options, text='Done', command=root.destroy)
detect_button.grid(column=0, row=0)
done_button.grid(column=1, row=0)
root.mainloop()
理想情况下,在函数update_list终止后,Entry小部件将保留(并保持填充!)。我还希望能够从函数外部与这些小部件的内容进行交互。
目前,Entry字段在函数update_list的过程中填充,然后在结束时立即减少。我怀疑这是因为小部件及其内容的范围不是全局的。
在textvariable=species_elem_list
你使用局部变量species_elem_list
当你退出update_list()
时停止存在
当你做species_elem_list
时,你必须在update_list()
之外创建global species_elem_list
并在update_list()
中使用species_elem_list = []
来使用全局变量而不是本地变量
from Tkinter import *
import ttk
from time import sleep
species_elem_list = [] # <--- put here or below of update_list
def update_list(manager, rows):
global species_elem_list # <-- use global variable instead of local one
species_list = ['A','B','C','D']
del rows[1:]
for widget in manager.children.values():
widget.grid_forget()
if not species_list == ['']:
species_elem_list = []
for i, each in enumerate(species_list):
## Here I attempt to create a dynamic list of StringVars to attach to the Entry fields below, based on the contents of the species list.
species_elem_list.append(StringVar())
## Here I initialize the values of the elements of the Entry fields by setting the StringVar of each.
species_elem_list[i].set(each)
## I tried to attach the value of the StringVar (from the species list) to the Entry below, but when the program is run, the Entry does not stay populated.
temp_name = ttk.Entry(manager, textvariable=species_elem_list[i], state='readonly')
temp_color = ttk.Label(manager, text='data')
temp_row = [temp_name, temp_color]
rows.append(temp_row)
for row_number in range(len(rows)):
for column_number, each in enumerate(rows[row_number]):
each.grid(column=column_number, row=row_number)
each.grid()
manager.update()
sleep(3) ## Included so that the population of the fields can be observed before they depopulate.
## After this point, the update_list function terminates.
## When that happens, the Entry fields depopulate. How can I get them to persist after the function terminates?
root = Tk()
manager = ttk.Frame(root, padding='4 5 4 4')
manager.grid(column=0, row=0, sticky=NSEW)
name_label = ttk.Label(manager, text='Name')
color_label = ttk.Label(manager, text='RGB')
rows = [[name_label, color_label]]
options = ttk.Frame(root)
options.grid(sticky=NSEW)
detect_button = ttk.Button(options, text='Auto-Detect', command=lambda: update_list(manager,rows))
done_button = ttk.Button(options, text='Done', command=root.destroy)
detect_button.grid(column=0, row=0)
done_button.grid(column=1, row=0)
root.mainloop()