我似乎无法让tkinter内置的小部件虚拟事件工作。
似乎command =
工作,但我不能使用它,因为它不返回tkinter事件参数回调函数。我需要将tkinter事件参数返回给回调,以便获得调用小部件的实例。
我做错了什么'<<ComboboxSelected>>'
,'<<Increment>>'
,'<<Decrement>>'
什么都不做吗?
我需要调用回调并传递事件,这样我才能获得小部件实例。我也不能使用lambda(正如所有类似示例所建议的那样)来返回索引号,因为我需要在打算删除行时直接访问小部件以获取其当前行号。如果我用,它会把事情弄得一团糟,因为索引是固定的。如果我点击第5行,删除第5行,第6行变成第5行如果我想删除它会删除第6行。
我还希望有一个虚拟事件按钮执行相同的效果的命令。所以如果你按下按钮,按空格键或点击它,但我找不到任何这样的虚拟事件。有这样的东西吗?
from tkinter import *
root = Tk()
omuVars = []
omuList = ['Bahamas','Canada', 'Cuba','United States']
omu = []
spb = []
cmd = []
def callSelectChanged(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callIncrement(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callDecrement(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callButton(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
for i in range(0,10):
omuVars.append(StringVar())
omu.append(OptionMenu(root,
omuVars[i],
*omuList))
omu[i].bind('<<ComboboxSelected>>', callSelectChanged)
omu[i].config(font='Terminal 18 bold', anchor=W, fg='blue', relief=FLAT, bg='SystemWindow', borderwidth=0, width=15)
omu[i].grid(row=i, column=0)
spb.append(Spinbox(root,
from_=00,
to=23,
wrap=True,
width=2,
font='Terminal 18 bold',
fg='blue',
format="%02.0f",
relief=FLAT))
spb[i].bind('<<Increment>>', callIncrement)
spb[i].bind('<<Decrement>>', callDecrement)
spb[i].grid(row=i, column=1)
cmd.append(Button(root,
text='u2718',
font='Terminal 16 bold',
fg='blue',
width=2))
cmd[i].bind('<Button-1>',callButton)
cmd[i].bind('<space>', callButton)
cmd[i].grid(row=i, column=2)
root.mainloop()
tkinterOptionMenu
部件不生成<<ComboboxSelected>>
事件,tkinterSpinbox
部件不生成<<Increment>>
或<<Decrement>>
事件。在这些小部件上绑定这些事件将不起作用。
要使这些事件和绑定工作,您需要使用ttk中的Combobox
和Spinbox
小部件。
根据事件的文档,<<Increment>>
和<<Decrement>>
不是预定义的虚拟事件。
另外,OptionMenu
不支持<<ComboboxSelected>>
。这需要ttk.Combobox
小部件。
关于在spinbox中,tkinter
仅在发生更改时调用command
。但是,这个调用不包含event
。我的解决方法是将不同的参数提交到相同的回调,这是functools.partial
。
OptionMenu
的command
回调接收的不是事件,而是选择的字符串。修改后的代码如下:
修改代码。我还使用了tk命名空间而不是import *
。
from functools import partial
import tkinter as tk
root = tk.Tk()
omuVars = []
omuList = ["Bahamas", "Canada", "Cuba", "United States"]
omu = []
spb = []
cmd = []
def callSelectChanged(selection):
print(f"callSelectChanged: {selection}")
def callSpinChanged(index):
print(f"callSpinChanged: {index}")
def callButton(event):
caller = event.widget
rowNumber = caller.grid_info()["row"]
print(f"callButton: {rowNumber}")
for i in range(0, 10):
omuVars.append(tk.StringVar())
omu.append(tk.OptionMenu(root, omuVars[i], *omuList, command=callSelectChanged))
omu[i].config(
fg="blue",
font="Terminal 18 bold",
relief="flat",
borderwidth=0,
width=15,
)
omu[i].grid(row=i, column=0)
spb.append(
tk.Spinbox(
root,
from_=0,
to=23,
wrap=True,
width=2,
font="Terminal 18 bold",
fg="blue",
format="%02.0f",
relief=tk.FLAT,
command=partial(callSpinChanged, index=i),
)
)
spb[i].grid(row=i, column=1)
cmd.append(
tk.Button(root, text="u2718", font="Terminal 16 bold", fg="blue", width=2)
)
cmd[i].bind("<Button-1>", callButton)
cmd[i].bind("<space>", callButton)
cmd[i].grid(row=i, column=2)
root.mainloop()
从tkinter切换到ttk解决了这个问题:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
cmbVars = []
cmbList = ['Bahamas','Canada', 'Cuba','United States']
cmb = []
spb = []
cmd = []
# Define the style for combobox widget
style= ttk.Style(root)
#print(style.theme_names()) #('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
style.theme_use('default')
style.configure("TCombobox", font='Terminal 18 bold' , anchor=tk.W, foreground='blue', relief='flat', background='SystemWindow', borderwidth=0, width=15, arrowcolor='blue', arrowsize=18)
# I don't understand why ttk ignores the following style settings unless I specify it here and in this order.
style.map('TCombobox', fieldbackground=[('readonly','SystemWindow')])
style.map('TCombobox', selectbackground=[('readonly', 'SystemWindow')])
style.map('TCombobox', selectforeground=[('readonly', 'blue')])
style.configure("TButton", font='Terminal 16 bold', anchor=tk.W, foreground='blue', relief='flat', background='SystemWindow', borderwidth=0, width=2)
style.configure("TSpinbox", font='Terminal 18 bold', anchor=tk.W, foreground='blue', relief='flat', background='SystemWindow', borderwidth=0, width=2, arrowcolor='blue', arrowsize=18)
print()
def callSelectChanged(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callIncrement(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callDecrement(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
def callButton(event):
caller = event.widget
rowNumber = caller.grid_info()['row']
print(rowNumber)
for i in range(0,10):
cmbVars.append(tk.StringVar())
cmb.append(ttk.Combobox(root,
textvariable=cmbVars[i],
state="readonly",
style="TCombobox",
font=style.lookup('TCombobox', 'font')))
cmb[i]['values'] = cmbList
cmb[i].bind('<<ComboboxSelected>>', callSelectChanged)
cmb[i].grid(row=i, column=0)
spb.append(ttk.Spinbox(root,
from_=00,
to=23,
wrap=True,
format="%02.0f",
style="TSpinbox",
font=style.lookup('TSpinbox', 'font'),
foreground=style.lookup('TSpinbox', 'foreground'),
background=style.lookup('TSpinbox', 'background'),
width=style.lookup('TSpinbox', 'width')))
spb[i].bind('<<Increment>>', callIncrement)
spb[i].bind('<<Decrement>>', callDecrement)
spb[i].grid(row=i, column=1)
cmd.append(ttk.Button(root,
text='u2718',
style="TButton"))
cmd[i].bind('<Button-1>',callButton)
cmd[i].bind('<space>', callButton)
cmd[i].grid(row=i, column=2)
root.mainloop()