核心提示:接上一篇博文(Listbox 与 Scrollbar 联动设置),接下来该说说事件的事情了。还是先上代码:from tkinter import *from tkinter import messag...
接上一篇博文(Listbox 与 Scrollbar 联动设置),接下来该说说事件的事情了。
还是先上代码:
from tkinter import * from tkinter import messagebox class Win_Program: def __init__(self): self.master = Tk() self.master.state("zoomed") # 窗口最大化 self.master.title("demo") self.master.grid() self.databases = list() self.var = StringVar() for i in range(40): self.databases.append("database"+str(i)) def get_db_configure(self): top = Toplevel(self.master) top.title("数据库配置") top.resizable(0,0) # 大小不可变 # 创建的Toplevel对象 在最上层 top.attributes("-toolwindow", 1) top.wm_attributes("-topmost", 1) top.grid() sb = Scrollbar(top) sb.grid(row=0, rowspan=20, sticky=E+NS, padx=10, pady=5, column=1) lb = Listbox(top, listvariable=self.var, width=65, yscrollcommand=sb.set, selectmode=SINGLE, height=20) lb.bind(sequence='', func=self.handler_adaptor(self.handler, lb=lb, top=top)) for i in range(len(self.databases)): lb.insert(0, self.databases[i]) lb.grid(row=0, rowspan=20, column=0, padx=5, pady=5) # Listbox 滚动时,通过lb.yview方法 通知到 Scrollbar 组件 sb.config(command=lb.yview) return top def widget_to_center(self, master, width, height): # 获取屏幕长/宽 self.width = self.master.winfo_screenwidth() self.height = self.master.winfo_screenheight() x = self.width / 2 - width / 2 y = self.height / 2 - height / 2 master.geometry('%dx%d+%d+%d' % (width, height, x, y)) master.grid() print(self.width, self.height, x, y) def handler(self, event, top, lb): """事件处理函数""" content = lb.get(lb.curselection()) return messagebox.showinfo(title="Hey, you got me!", message="I am {0}".format(content), parent=top) def handler_adaptor(self, fun, **kwds): """事件处理函数的适配器,相当于中介,那个event是从那里来的呢,我也纳闷,这也许就是python的伟大之处吧""" return lambda event, fun=fun, kwds=kwds: fun(event, **kwds) if __name__ == "__main__": win_program = Win_Program() win_program.widget_to_center(win_program.get_db_configure(), 500, 400) mainloop()
在上一篇文章中,我们能展示所有数据库配置了。接下来需要一个事件绑定,来完成选择配置的过程。绑定事件用bind方法,事件绑定有很多,一般通过鼠标/键盘能实现的操作,都可以绑定,比如:单击,双击,组合键ctrl+c,组合键 ctrl_v等。在我们这个案例中,双击选中是一个实用的操作。故:
lb.bind(sequence='', func=self.handler_adaptor(self.handler, lb=lb, top=top))
需要注意的是,bind方法sequence入参是描述鼠标、键盘的操作事件,func入参可传入一个调用函数,但传递的函数必须是一个带event参数的方法,而且只能有这么一个参数。举个例子:
定义如下函数:
def no_other_argues(self, event): print("You got me!")
bind方法func入参可换成这样:
lb.bind(sequence='', func=self.no_other_argues)
双击,可以在运行代码窗口看到输出。
重点来了
但很多时候,不支持传递参数的bind方法,并不能满足我们的需求。若需要bind方法的func入参支持多参数,该如何解决呢?这个只能曲线救国了,需要定义一个函数中介:
def handler_adaptor(self, fun, **kwds): """事件处理函数的适配器,相当于中介,那个event是从那里来的呢,我也纳闷,这也许就是python的伟大之处吧""" return lambda event, fun=fun, kwds=kwds: fun(event, **kwds)
然后再定义自己真正要执行的函数:
def handler(self, event, top, lb): """事件处理函数""" content = lb.get(lb.curselection()) return messagebox.showinfo(title="Hey, you got me!", message="I am {0}".format(content), parent=top)
如此,bind方法就能支持参数传递了。
最终效果如下: