cget 在 tkinter 中的成员测试中在哪里?

huangapple go评论65阅读模式
英文:

Where is cget in membership test in tkinter?

问题

在第17行花了相当长的时间来查看(请参见下面的setaview()),并试图理解整数、字符串和连接的位置。

if clsname in vcache22:  # 第17行

错误

TypeError: can only concatenate str (not "int") to str

在第21行引入:正确的行应该是:

vcache22[clsname] = aview = cls()

终端会话:

$ python setaview.py
setaview(Track)
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
    return self.func(*args)
  File "/home/vlz/Documents/ARCHIVE/musicbox/setaview.py", line 36, in <lambda>
    command=lambda x=t: setaview(x))
  File "/home/vlz/Documents/ARCHIVE/musicbox/setaview.py", line 17, in setaview
    if clsname in vcache22:
  File "/usr/lib/python3.9/tkinter/__init__.py", line 1652, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str

带有错误的函数:

def setaview(clsname):
    global vcache22, aview
    if clsname in vcache22:  # 第17行
        aview = vcache22[clsname]
    else:
        cls = getattr(sys.modules['__main__'], clsname)
        vcache22 = aview = cls()  # 第21行
    # 为了表示已经完成了某事
    print(f'setaview({clsname})')

这是为了隔离我在其他较长代码中找到的问题而制作的假设性示例。完整的脚本如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import tkinter as tk
from tkinter import ttk
aview = None
vcache22 = {}


class Track(tk.Listbox): pass  # noqa
class Album(tk.Listbox): pass  # noqa
class Playlist(tk.Listbox): pass  # noqa


def setaview(clsname):
    global vcache22, aview
    if clsname in vcache22:
        aview = vcache22[clsname]
    else:
        cls = getattr(sys.modules['__main__'], clsname)
        vcache22 = aview = cls()
    # 为了表示已经完成了某事
    print(f'setaview({clsname})')


def main():
    root = tk.Tk()
    box = tk.Frame(root)
    box.grid(column=0, row=0)
    selected = tk.StringVar()
    i = 0
    for t in 'Track', 'Album', 'Playlist':
        rb = ttk.Radiobutton(
            box, text=t, value=t, variable=selected,
            command=lambda x=t: setaview(x))
        rb.grid(column=i, row=0)
        i += 1
        if t == 'Track':
            rb.invoke()
    tk.mainloop()


if __name__ == '__main__':
    main()

使用: Python 3.9.2 Debian GNU/Linux 11(bullseye)

英文:

I spent quite a while looking at the line 17 (see setaview() below) and trying to comprehend where were the int, string and concatenation.

if clsname in vcache22:  # line 17

The error

TypeError: can only concatenate str (not "int") to str

was introduced in the line 21: The right line should be:

vcache22[clsname] = aview = cls()

The terminal session:

$ python setaview.py
setaview(Track)
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
    return self.func(*args)
  File "/home/vlz/Documents/ARCHIVE/musicbox/setaview.py", line 36, in <lambda>
    command=lambda x=t: setaview(x))
  File "/home/vlz/Documents/ARCHIVE/musicbox/setaview.py", line 17, in setaview
    if clsname in vcache22:
  File "/usr/lib/python3.9/tkinter/__init__.py", line 1652, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str

The function with the error:

def setaview(clsname):
    global vcache22, aview
    if clsname in vcache22:  # line 17
        aview = vcache22[clsname]
    else:
        cls = getattr(sys.modules['__main__'], clsname)
        vcache22 = aview = cls()  # line21
    # To indicate that smth has done
    print(f'setaview({clsname})')

This is the contrived example to isolate the problem I found in other longer code. The full script is below:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import tkinter as tk
from tkinter import ttk
aview = None
vcache22 = {}


class Track(tk.Listbox): pass  # noqa
class Album(tk.Listbox): pass  # noqa
class Playlist(tk.Listbox): pass  # noqa


def setaview(clsname):
    global vcache22, aview
    if clsname in vcache22:
        aview = vcache22[clsname]
    else:
        cls = getattr(sys.modules['__main__'], clsname)
        vcache22 = aview = cls()
    # To indicate that smth has done
    print(f'setaview({clsname})')


def main():
    root = tk.Tk()
    box = tk.Frame(root)
    box.grid(column=0, row=0)
    selected = tk.StringVar()
    i = 0
    for t in 'Track', 'Album', 'Playlist':
        rb = ttk.Radiobutton(
            box, text=t, value=t, variable=selected,
            command=lambda x=t: setaview(x))
        rb.grid(column=i, row=0)
        i += 1
        if t == 'Track':
            rb.invoke()
    tk.mainloop()


if __name__ == '__main__':
    main()

Using:
Python 3.9.2
Debian GNU/Linux 11 (bullseye)

答案1

得分: 1

在tkinter的成员测试中,cget在哪里?

在Python中,当你执行x in y时,Python内部会调用方法__getitem__。所以,当你执行if clsname in vcache22时,它调用了对象的__getitem__方法,而在这种情况下,该对象是Listbox的子类。对于tkinter小部件,__getitem__被别名为cget。这就是为什么在这种情况下调用cget的原因。

错误消息指向了tkinter/init.py的第1652行。如果你查看该行,你可能会看到在这一行稍微下面的几行:

__getitem__ = cget

这是所有小部件的基类定义中的一部分。

英文:

> Where is cget in membership test in tkinter?

In python, when you do x in y, internally python will call the method __getitem__. So, when you do if clsname in vcache22 it's calling __getitem__ of the object, which in this case is a subclass of Listbox. For tkinter widgets, __getitem__ is aliased to cget. That is why cget is being called in this case.

The error message is pointing you to line 1652 of tkinter/init.py. If you look at that line, you might see just a couple lines further down this line:

__getitem__ = cget

This is in the definition of the base class for all widgets.

huangapple
  • 本文由 发表于 2023年7月13日 17:30:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76677885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定