【问题标题】:Python 3.8. Why I'm missing 2 required positional arguments: 'event' and 'cmb'?蟒蛇 3.8。为什么我缺少 2 个必需的位置参数:“事件”和“cmb”?
【发布时间】:2022-01-04 05:20:08
【问题描述】:

当我使用组合框时,脚本打印正常。但是当我使用按钮“获取选项列表”时,我收到错误消息“get_combo_choice() 缺少 2 个必需的位置参数:'event' 和 'cmb'”。我想不通。感谢您的任何提示。

import tkinter as tk
from tkinter import  ttk
from tkinter import Tk
from tkinter import Button

root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']
# result =[]

# def get_combo_choice(event, cmb):
#     result.append(cmb.get())
#     print(result)
result =[None, None, None]
best = []

# Here's the alternative 
def get_combo_choice(event, cmb):
    i = best.index(event.widget)
    result[i] = cmb.get()
    print('result-->', result)    
    print('i-->', i)
    print('event.widget-->', event.widget)
    print('cmb.get-->', cmb.get())
    print('result[i]-->', result[i])
          
          
          
for index, heroe in enumerate(my_heroes):
    var = tk.StringVar()
    bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
    best.append(bestPlayers)
    bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
    
    label = tk.Label(root, text = heroe)
    label.grid(row=0 + index, column=0,padx=(15,25))

    bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var: get_combo_choice(event, cmb))

    
    button = tk.Button(root, text ="get list of choices", command = get_combo_choice)
    button.grid(row=4, column=0,padx=(15,25))

root.mainloop()

错误是:

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\python\python38\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
TypeError: get_combo_choice() missing 2 required positional arguments: 'event' and 'cmb'

【问题讨论】:

  • 正如错误所说,按钮的command 选项的回调不需要参数。
  • 您在每次迭代中创建了一个按钮并将其放在同一单元格(行=4,列=0)中,因此只能看到最后一个按钮。是否应该在 for 循环之外创建按钮?

标签: python python-3.x tkinter combobox


【解决方案1】:

[更新]

您可以使用以下内容:

button = tk.Button(root, text ="get list of choices")
button.grid(row=4, column=0,padx=(15,25))
button.bind("<Button-1>", lambda event, cmd=var: get_combo_choice(event, var))

由于您的函数 get_combo_choice(event, cmd) 有两个位置参数,因此您需要在调用函数时提供它们:

这引发了与 best.index 有关的不同错误

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Users/nishanth.reddy/miniconda3/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
    return self.func(*args)
  File "<ipython-input-11-e63f934a14cb>", line 43, in <lambda>
    button.bind("<Button-1>", lambda event, cmd=var: get_combo_choice(event, var))
  File "<ipython-input-11-e63f934a14cb>", line 19, in get_combo_choice
    i = best.index(event.widget)
ValueError: <tkinter.Button object .!button3> is not in list

如果你的函数需要参数,你可以使用 lambda,比如:

button = tk.Button(
    root, 
    text ="get list of choices", 
    command=lambda : get_combo_choice(event, cmb) # will raise NameError
)

但是这里的重点是,点击按钮的时候没有传递event。参考:How to handle a Button click event

python def button_press_handle(callback=None):
    if callback:         
        callback() # Where exactly the method assigned to btn['command'] is being callled

如果您确实想要一个event 对象,那么也许您可以创建一个虚拟的本地事件对象并在调用您的函数时传递它。

创建虚拟事件对象:

        e = tkinter.Event()
        e.serial = 12345
        e.num = '??'
        e.height = '??'
        e.keycode = '??'
        e.state = 0
        e.time = 123456789
        e.width = '??'
        e.x = '??'
        e.y = '??'
        e.char = ''
        e.keysym = '??'
        e.keysym_num = '??'
        e.type = '100' # or tk.EventType.ButtonPress
        e.widget = '??'
        e.x_root = '??'
        e.y_root = '??'
        e.delta = 0

获得按钮点击事件的一种方法是使用button.bind("&lt;Button-1&gt;", lambda event: get_combo_choice(event, None))

【讨论】:

  • 在哪里可以获得eventcmb 对象?
  • 当按钮被点击时,看起来下面的方法被称为python def button_press_handle(callback=None): if callback: callback() # Where exactly the method assigned to btn['command'] is being callled ,其中callback是命令参数。
  • 是的,我知道,但你会得到例外:NameError: name 'event' is not defined
  • 结果已经存储在您的全局变量result 中,对吗?因此,您可以再创建一个函数并将其与按钮单击事件相关联,它可以使用结果,如果您也想记住选择,也许在存储结果时,还要记住哪个索引在某个全局字典或元组中。
  • 只需使用函数def get_result(): print(result) 并使用button = tk.Button(root, text ="get list of choices", command = get_result) 您也可以在循环外使用此函数,因为每当有人单击get_list_of_choices 按钮时它就会打印出结果
【解决方案2】:

我缩小到“最小”尺寸,并按照您的指示,它现在正在工作,“非常感谢”:

from tkinter import  ttk
from tkinter import Tk
from tkinter import Button

root = Tk()
my_heroes = ['Zidane', 'Ronaldo', 'Messi']
position = ['The One!', 'more or less','the bad']


def get_combo_choice(event, cmb):
    i = best.index(event.widget)
    result[i] = cmb.get()


def get_result(): 
    print(result)  
    
    
result =[None, None, None]
best = []
       
combobox_in_loop = ['None']*3
combobox_get = []            
for index, heroe in enumerate(my_heroes):
    var = tk.StringVar()
    bestPlayers = ttk.Combobox(root,values=position, textvariable=var, state="readonly")
    best.append(bestPlayers)
    bestPlayers.grid(row=0 + index, column=1,padx=(15,25))
    bestPlayers.bind("<<ComboboxSelected>>",lambda event, cmb=var: get_combo_choice(event, cmb))
#     bestPlayers.bind("<<ComboboxSelected>>", lambda event:callbackFunc(event))
    combobox_in_loop.append(bestPlayers) # = saves names of comboboxes
    combobox_get.append(bestPlayers.get())
    

button = tk.Button(root,text ="this is wrong", command=get_combo_choice )
button.grid(row=4, column=0)

button2 = tk.Button(root, text ="correct: get list of choices", command = get_result)
button2.grid(row=5, column=0)

root.mainloop()

 

【讨论】:

  • result--> ['the bad', 'The One!', 'more or less']
猜你喜欢
  • 2015-04-25
  • 2019-02-08
  • 2021-07-22
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 2021-06-30
  • 2019-04-26
  • 1970-01-01
相关资源
最近更新 更多