酸洗后无法绑定功能 - tkinter

Unable to bind function after pickling - tkinter

我有一个简单的代码,可以通过按一个按钮来创建两个字段。还有另外两个按钮用于保存和加载创建的输入字段。我已经使用 bind 函数绑定字段 A 和字段 B。输入数字后在字段 A 上按 Enter 按钮将在字段 B 中打印出其值乘以 5 .此时bind功能完美运行

当我创建三个输入字段并在不输入任何输入的情况下保存进度并编译程序,然后加载文件时,绑定功能似乎不起作用。它似乎只适用于最后创建的字段。我的代码如下。我尽量简化代码。

from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfile
from tkinter import messagebox
import pickle

class Test(Frame):

    def Widgets(self):

        self.button_add = Button(self, text = "Add", command = self.add)
        self.button_add.grid(row=0, column =2)

        self.button_save = Button(self, text = "save", command = self.save)
        self.button_save.grid(row=0, column =3)

        self.button_load = Button(self, text = "load", command = self.load)
        self.button_load.grid(row=0, column =4)

    def add(self):

        def test(event):
            self.field_B[n].delete(0, END)
            self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)

        self.field_A.append({})
        n = len(self.field_A)-1
        self.field_A[n] = Entry(self)
        self.field_A[n].grid(row=n, column =0)
        self.field_A[n].bind("<Return>", test)

        self.field_B.append({})
        n = len(self.field_B)-1
        self.field_B[n] = Entry(self)
        self.field_B[n].grid(row=n, column =1)

    def save(self):
        for n in range(len(self.field_A)):
            self.entry_A.append(self.field_A[n].get())
            self.entry_B.append(self.field_B[n].get())

        fname = asksaveasfile(mode = "w", defaultextension = ".est")
        data = {"fields": len(self.field_A), "entries_A": (self.entry_A),"entries_B": (self.entry_B)}

        with open(fname.name, "wb") as file:
            pickle.dump(data, file)

    def load(self):

        def test(event):
            print("Why is the value of n always equal to", n, "?")
            self.field_B[n].delete(0, END)
            self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)

        fname = askopenfilename(filetypes = (("Estimation Files (est)", "*.est"),))
        location = fname.replace("/", "\")
        if location:
            with open(location, "rb") as file:
                data = pickle.load(file)

            for n in range(data["fields"]):
                self.field_A.append({})
                self.field_A[n] = Entry(self)
                self.field_A[n].grid(row=n, column =0)
                self.field_A[n].insert(0, data["entries_A"][n])
                self.field_A[n].bind("<Return>", test)

                self.field_B.append({})
                self.field_B[n] = Entry(self)
                self.field_B[n].grid(row=n, column =1)
                self.field_B[n].insert(0, data["entries_B"][n])

    def __init__(self,master = None):
        Frame.__init__(self, master)
        self.field_A = []
        self.field_B = []
        self.entry_A = []
        self.entry_B = []
        self.grid()
        self.Widgets()

root = Tk()
app = Test(master = None)
app.mainloop()

您需要 "closure"。您可以使用 functools.partial 函数在 python 中进行闭包。

from functools import partial

def test(n, event=None):
    self.field_B[n].delete(0, END)
    self.field_B[n].insert(0, (float(self.field_A[n].get()))*5)

#other code ... 

self.field_A[n].bind("<Return>", partial(test, n))

您的两个 test() 函数都从封闭函数访问变量 n。在add()的情况下,没有循环; n 有一个值。每个条目的 test() 都有自己的 n,因为它们被对 add() 的不同调用所绑定。但是,在 load() 中,您正在遍历 n 个值;每个 test() 指的是同一个 n,在可能调用任何绑定时,它将具有其最终值。另一个答案给出了一种合理的方式来为 test() 的每个实例提供自己的个人 n,所以我不会在这里重复。