使用 tkinter 时是否有深度复制的替代方案?

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

在使用 tkinter 时遇到问题,这是我正在做的一个简单示例

import tkinter as tk
from tkinter import ttk
from typing import Any, Callable, Mapping, NamedTuple, Type


values = {
        'eat': ('something', 'nice'),
        'dirt': ('something', 'else'),
        'kid': ('something'), '': tuple()
    }

class MyTuple(NamedTuple):
    widget: Type[tk.Widget]
    config: Mapping[str, Any] = {}
    postcommand: Callable[[ttk.Combobox], None] = None


class Reg():
    def __init__(self, var):
        self.var = var
        self.widgets = (
                MyTuple(ttk.Label),
                MyTuple(ttk.Combobox, {'values': tuple(values.keys()), 'textvariable': self.var}),
                MyTuple(ttk.Combobox, postcommand=self.cb),
                MyTuple(ttk.Combobox, postcommand=self.other_cb),
            )

    def display(self, frame: tk.Tk):
        for w in self.widgets:
            widget = w.widget(frame, **w.config)
            widget.pack()
            if not w.postcommand is None:
                widget['postcommand'] = lambda widget=widget : w.postcommand(widget)

    def cb(self, combobox: ttk.Combobox):
        combobox['values'] = values[self.var.get()]

    def other_cb(self, combobox: ttk.Combobox):
        combobox['values'] = tuple(values.keys())


class GUI(tk.Tk):
    def __init__(self):
        super().__init__()
        v = tk.StringVar()
        reg = Reg(v)
        reg.display(self)

_ = GUI()
_.mainloop()

运行此程序时,似乎 w 被覆盖并且为所有组合框设置了相同的后置命令。我尝试将显示更改为如下所示:

from copy import deepcopy

...

    def display(self, frame: tk.Tk):
        for w in self.widgets:
            widget = w.widget(frame, **w.config)
            widget.pack()
            if not w.postcommand is None:
                command = deepcopy(w.postcommand)
                widget['postcommand'] = lambda widget=widget : command(widget)

我得到错误

TypeError: cannot pickle '_tkinter.tkapp' object
.

我可以使用 deepcopy 的替代方法吗?我所能找到的只是一种覆盖 pickle 函数的方法,但我无法弄清楚如何在这里应用它,因为我什至无法弄清楚什么 tkinter 对象是 deepcopy 的一部分。

或者,有没有办法解决 w 的作用域问题?

(使用 python 3.8.10)

python-3.x tkinter deep-copy
1个回答
0
投票

调用

w.postcommand
的 lambda 没有捕获
w
的正确值。如果将循环中的 lambda 更改为此会发生什么?

widget['postcommand'] = lambda widget=widget, w=w: w.postcommand(widget)

进一步阅读:lambda 函数闭包捕获什么?

© www.soinside.com 2019 - 2024. All rights reserved.