在创建它们的函数终止后,如何保持动态输入字段的填充?

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

我正在使用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的过程中填充,然后在结束时立即减少。我怀疑这是因为小部件及其内容的范围不是全局的。

python-2.7 tkinter ttk
1个回答
0
投票

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()
© www.soinside.com 2019 - 2024. All rights reserved.