首页 > 解决方案 > 解决 Tkinter 中的循环变量依赖性

问题描述

假设我有一个自定义小部件,它本质上是两个字段,每个字段都有一个 tkinter StringVar/IntVar与之关联。目标是让这个自定义小部件允许拥有它自己的变量成员,您可以将其传递给它并像使用大多数基本组件一样使用,在您绑定到它的地方,使用它的获取和设置来读取/更新小部件值分别。

我遇到的问题是,我能想到的任何配置都会导致形成无限循环的循环引用问题。请参阅下面我尝试的示例:

from tkinter import IntVar, StringVar
from tkinter.ttk import Frame, Entry


class CustomWidget(Frame):
    def __init__(self, master, textvariable=None, **kw):
        super().__init__(master, **kw)
        self._variable = textvariable or StringVar()

        self._variable.trace_add('write', self._on_external_change)

        self._entry_internal_var = IntVar(self)
        self._entry = Entry(self, textvariable=self._entry_internal_var)
        self._entry.pack()

        self._other_entry_interval_var = StringVar(self)
        self._other_entry = Entry(self, textvariable=self._other_entry_interval_var)
        self._other_entry.pack()

        self._entry_internal_var.trace_add('write', self._on_value_changed)
        self._other_entry_interval_var.trace_add('write', self._on_value_changed)

    def _on_value_changed(self, *_, **__):
        self._variable.set('{}_{}'.format(self._entry_internal_var.get(),
                                          self._other_entry_interval_var.get()))

    def _on_external_change(self, *_, **__):
        temp = self._parse_string_into_value(self._variable.get())
        self._entry_internal_var.set(temp[0])
        self._other_entry_interval_var.set(temp[1])

    @staticmethod
    def _parse_string_into_value(value: str):
        temp = value.split('_')
        return int(temp[0]), temp[1]

我这样做的原因是因为我希望能够对传递给__init__方法的变量使用变量更新回调,但显然我遇到了问题,每次更新都会导致一个循环,其中_variable的跟踪方法更新我的内部变量,并且它们导致更新_variable

所以我的问题是,无论如何修改传递变量的值而不引起这种循环?

标签: pythontkintercircular-reference

解决方案


推荐阅读