接上一篇博文 (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 方法就能支持参数传递了.
最终效果如下:
来源: https://www.2cto.com/kf/201806/757459.html