如何在 tkinter 中创建全局变量类

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

我需要创建一个像 StringVar 这样的变量,但又像一个列表的列表(行/列表)。我阅读了 tkinter 文件并找到了一个名为“Variable”的类,所有其他类都继承了该类。我尝试制作自己的变量,但我的 IDE 给我一个错误。在 Lib 文件的类变量中,变量创建两个类变量:“_tk”和“_name”。但是当我从这个类继承时,我的 IDE 告诉我:

类“ListVar”的未解析属性引用“_tk”

与“_name”相同的问题。

源代码:


class Variable:
    """Class to define value holders for e.g. buttons.

    Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
    that constrain the type of the value returned from get()."""
    _default = ""
    _tk = None
    _tclCommands = None

    def __init__(self, master=None, value=None, name=None):
        """Construct a variable

        MASTER can be given as master widget.
        VALUE is an optional value (defaults to "")
        NAME is an optional Tcl name (defaults to PY_VARnum).

        If NAME matches an existing variable and VALUE is omitted
        then the existing value is retained.
        """
        # check for type of NAME parameter to override weird error message
        # raised from Modules/_tkinter.c:SetVar like:
        # TypeError: setvar() takes exactly 3 arguments (2 given)
        if name is not None and not isinstance(name, str):
            raise TypeError("name must be a string")
        global _varnum
        if not master:
            master = _default_root
        self._root = master._root()
        self._tk = master.tk
        if name:
            self._name = name
        else:
            self._name = 'PY_VAR' + repr(_varnum)
            _varnum += 1
        if value is not None:
            self.initialize(value)
        elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)):
            self.initialize(self._default)

    def __del__(self):
        """Unset the variable in Tcl."""
        if self._tk is None:
            return
        if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
            self._tk.globalunsetvar(self._name)
        if self._tclCommands is not None:
            for name in self._tclCommands:
                #print '- Tkinter: deleted command', name
                self._tk.deletecommand(name)
            self._tclCommands = None

    def __str__(self):
        """Return the name of the variable in Tcl."""
        return self._name

    def set(self, value):
        """Set the variable to VALUE."""
        return self._tk.globalsetvar(self._name, value)

    initialize = set

    def get(self):
        """Return value of variable."""
        return self._tk.globalgetvar(self._name)

    def _register(self, callback):
        f = CallWrapper(callback, None, self._root).__call__
        cbname = repr(id(f))
        try:
            callback = callback.__func__
        except AttributeError:
            pass
        try:
            cbname = cbname + callback.__name__
        except AttributeError:
            pass
        self._tk.createcommand(cbname, f)
        if self._tclCommands is None:
            self._tclCommands = []
        self._tclCommands.append(cbname)
        return cbname

    def trace_add(self, mode, callback):
        """Define a trace callback for the variable.

        Mode is one of "read", "write", "unset", or a list or tuple of
        such strings.
        Callback must be a function which is called when the variable is
        read, written or unset.

        Return the name of the callback.
        """
        cbname = self._register(callback)
        self._tk.call('trace', 'add', 'variable',
                      self._name, mode, (cbname,))
        return cbname

    def trace_remove(self, mode, cbname):
        """Delete the trace callback for a variable.

        Mode is one of "read", "write", "unset" or a list or tuple of
        such strings.  Must be same as were specified in trace_add().
        cbname is the name of the callback returned from trace_add().
        """
        self._tk.call('trace', 'remove', 'variable',
                      self._name, mode, cbname)
        for m, ca in self.trace_info():
            if self._tk.splitlist(ca)[0] == cbname:
                break
        else:
            self._tk.deletecommand(cbname)
            try:
                self._tclCommands.remove(cbname)
            except ValueError:
                pass

    def trace_info(self):
        """Return all trace callback information."""
        splitlist = self._tk.splitlist
        return [(splitlist(k), v) for k, v in map(splitlist,
            splitlist(self._tk.call('trace', 'info', 'variable', self._name)))]

    def trace_variable(self, mode, callback):
        """Define a trace callback for the variable.

        MODE is one of "r", "w", "u" for read, write, undefine.
        CALLBACK must be a function which is called when
        the variable is read, written or undefined.

        Return the name of the callback.

        This deprecated method wraps a deprecated Tcl method that will
        likely be removed in the future.  Use trace_add() instead.
        """
        # TODO: Add deprecation warning
        cbname = self._register(callback)
        self._tk.call("trace", "variable", self._name, mode, cbname)
        return cbname

    trace = trace_variable

    def trace_vdelete(self, mode, cbname):
        """Delete the trace callback for a variable.

        MODE is one of "r", "w", "u" for read, write, undefine.
        CBNAME is the name of the callback returned from trace_variable or trace.

        This deprecated method wraps a deprecated Tcl method that will
        likely be removed in the future.  Use trace_remove() instead.
        """
        # TODO: Add deprecation warning
        self._tk.call("trace", "vdelete", self._name, mode, cbname)
        cbname = self._tk.splitlist(cbname)[0]
        for m, ca in self.trace_info():
            if self._tk.splitlist(ca)[0] == cbname:
                break
        else:
            self._tk.deletecommand(cbname)
            try:
                self._tclCommands.remove(cbname)
            except ValueError:
                pass

    def trace_vinfo(self):
        """Return all trace callback information.

        This deprecated method wraps a deprecated Tcl method that will
        likely be removed in the future.  Use trace_info() instead.
        """
        # TODO: Add deprecation warning
        return [self._tk.splitlist(x) for x in self._tk.splitlist(
            self._tk.call("trace", "vinfo", self._name))]

    def __eq__(self, other):
        """Comparison for equality (==).

        Note: if the Variable's master matters to behavior
        also compare self._master == other._master
        """
        return self.__class__.__name__ == other.__class__.__name__ \
            and self._name == other._name

StringVar 源代码:


class StringVar(Variable):
    """Value holder for strings variables."""
    _default = ""

    def __init__(self, master=None, value=None, name=None):
        """Construct a string variable.

        MASTER can be given as master widget.
        VALUE is an optional value (defaults to "")
        NAME is an optional Tcl name (defaults to PY_VARnum).

        If NAME matches an existing variable and VALUE is omitted
        then the existing value is retained.
        """
        Variable.__init__(self, master, value, name)

    def get(self):
        """Return value of variable as string."""
        value = self._tk.globalgetvar(self._name)
        if isinstance(value, str):
            return value
        return str(value)

我的源代码:


from tkinter import Variable
from typing import Optional


class ListVar(Variable):
    _default = []

    def __init__(self, master=None, value: Optional[list] = None, name: Optional[str] = None):
        """Construct a string variable.

        MASTER can be given as master widget.
        VALUE is an optional value (defaults to empty list)
        NAME is an optional Tcl name (defaults to PY_VARnum).

        If NAME matches an existing variable and VALUE is omitted
        then the existing value is retained.
        """
        Variable.__init__(self, master, value, name)

    def get(self):
        """Return value of variable as string."""
        value = self._tk.globalgetvar(self._name)
        if isinstance(value, str):
            return value
        return str(value)

python python-3.x variables tkinter global-variables
© www.soinside.com 2019 - 2024. All rights reserved.