英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论