如何将鼠标 click/move/drag 事件从自定义手柄标签重定向到 PanedWindow 父级
How to redirect mouse click/move/drag events from a custom grip Label to PanedWindow parent
我正在尝试为 Tkinter.PanedWindow
窗扇添加一个漂亮的把手。为此,我 place
一个 Label
在窗格旁边带有自定义手柄图像。示例:
from Tkinter import *
root = Tk()
pw = PanedWindow(root, orient=HORIZONTAL)
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=1)
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
griplabel = Label(pw, image=gripimg)
griplabel.place(relx=1, rely=0.5, anchor=W, in_=l1)
root.mainloop()
看起来不错。但现在标签与窗框重叠,窃取了鼠标事件,我无法通过拖动标签来调整 PanedWindow 的大小。如何让 griplabel
忽略鼠标事件并将它们全部重定向到 PanedWindow 窗扇?
我尝试了 ,但是:
griplabel.bindtags(pw.bindtags())
似乎没有做任何事情,即我仍然无法拖动 Label 来调整 PanedWindow 的大小。
或者是否有更好的方法为 PanedWindow 创建自定义句柄?
在 #tcl freenode channel 的帮助下,我想到了这个:
from Tkinter import *
root = Tk()
pw = PanedWindow(root, orient=HORIZONTAL)
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=True)
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
griplabel = Label(pw, image=gripimg, cursor="sb_h_double_arrow")
griplabel.place(relx=1, rely=0.5, anchor=W, in_=l1)
griplabel.bind("<Button-1>", lambda e:pw.event_generate("<Button-1>",x=e.x+griplabel.winfo_x(),y=e.y+griplabel.winfo_y()))
griplabel.bind("<B1-Motion>", lambda e:pw.event_generate("<B1-Motion>",x=e.x+griplabel.winfo_x(),y=e.y+griplabel.winfo_y()))
root.mainloop()
两次 griplabel.bind(...)
调用将 mousedown+mousemove 事件从 Label 转发到 PanedWindow,调整 x 和 y 坐标。这两个事件足以使窗扇移动。
并且 griplabel mouse "cursor" 设置为 sb_h_double_arrow
,因为根据 the Tk documentation:
,这是 PanedWindow 默认用于窗框的光标
Command-Line Name: -sashcursor
Mouse cursor to use when over a sash. If null, sb_h_double_arrow will be used for horizontal panedwindows, and sb_v_double_arrow will be used for vertical panedwindows.
也是cursor names recognized by Tk on all platforms之一。
TCL wiki mentions 另一种设置自定义窗扇把手的方法,使用 ttk.PanedWindow
和自定义 ttk.Style
布局:
from Tkinter import *
import ttk
root = Tk()
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
style = ttk.Style()
style.element_create("Sash.xsash", "image", gripimg, sticky=W+E)
style.layout("MySash.TPanedWindow", [('Sash.xsash', {})])
pw = ttk.PanedWindow(root, orient=HORIZONTAL, style="MySash.TPanedWindow")
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=True)
root.mainloop()
但它的外观和工作方式不同。本质上,它将 ttk.PanedWindow
的背景替换为平铺图像,该图像保持静态,并且窗扇成为在其上滑动的视口。这看起来很不寻常,但仍然有人会喜欢它。
我正在尝试为 Tkinter.PanedWindow
窗扇添加一个漂亮的把手。为此,我 place
一个 Label
在窗格旁边带有自定义手柄图像。示例:
from Tkinter import *
root = Tk()
pw = PanedWindow(root, orient=HORIZONTAL)
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=1)
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
griplabel = Label(pw, image=gripimg)
griplabel.place(relx=1, rely=0.5, anchor=W, in_=l1)
root.mainloop()
看起来不错。但现在标签与窗框重叠,窃取了鼠标事件,我无法通过拖动标签来调整 PanedWindow 的大小。如何让 griplabel
忽略鼠标事件并将它们全部重定向到 PanedWindow 窗扇?
我尝试了
griplabel.bindtags(pw.bindtags())
似乎没有做任何事情,即我仍然无法拖动 Label 来调整 PanedWindow 的大小。
或者是否有更好的方法为 PanedWindow 创建自定义句柄?
在 #tcl freenode channel 的帮助下,我想到了这个:
from Tkinter import *
root = Tk()
pw = PanedWindow(root, orient=HORIZONTAL)
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=True)
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
griplabel = Label(pw, image=gripimg, cursor="sb_h_double_arrow")
griplabel.place(relx=1, rely=0.5, anchor=W, in_=l1)
griplabel.bind("<Button-1>", lambda e:pw.event_generate("<Button-1>",x=e.x+griplabel.winfo_x(),y=e.y+griplabel.winfo_y()))
griplabel.bind("<B1-Motion>", lambda e:pw.event_generate("<B1-Motion>",x=e.x+griplabel.winfo_x(),y=e.y+griplabel.winfo_y()))
root.mainloop()
两次 griplabel.bind(...)
调用将 mousedown+mousemove 事件从 Label 转发到 PanedWindow,调整 x 和 y 坐标。这两个事件足以使窗扇移动。
并且 griplabel mouse "cursor" 设置为 sb_h_double_arrow
,因为根据 the Tk documentation:
Command-Line Name: -sashcursor
Mouse cursor to use when over a sash. If null, sb_h_double_arrow will be used for horizontal panedwindows, and sb_v_double_arrow will be used for vertical panedwindows.
也是cursor names recognized by Tk on all platforms之一。
TCL wiki mentions 另一种设置自定义窗扇把手的方法,使用 ttk.PanedWindow
和自定义 ttk.Style
布局:
from Tkinter import *
import ttk
root = Tk()
gripimg = PhotoImage(data="R0lGODlhBAAvAPEAALetnfXz7wAAAAAAACH5BAEAAAIALAAAAAAEAC8AAAIjRBwZwmKomjsqyVdXw/XSvn1RCFlk5pUaw42saL5qip6gnBUAOw==")
style = ttk.Style()
style.element_create("Sash.xsash", "image", gripimg, sticky=W+E)
style.layout("MySash.TPanedWindow", [('Sash.xsash', {})])
pw = ttk.PanedWindow(root, orient=HORIZONTAL, style="MySash.TPanedWindow")
l1 = Listbox(pw)
pw.add(l1)
l2 = Listbox(pw)
pw.add(l2)
pw.pack(fill=BOTH, expand=True)
root.mainloop()
但它的外观和工作方式不同。本质上,它将 ttk.PanedWindow
的背景替换为平铺图像,该图像保持静态,并且窗扇成为在其上滑动的视口。这看起来很不寻常,但仍然有人会喜欢它。