You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

全局使用tkinter的bind_all绑定事件时如何设置指定widget为例外?

实现方案

核心思路是在移动逻辑执行前做拦截判断,直接对比控件实例而非硬编码路径,稳定性和可维护性更高。

具体修改步骤

  1. 给Move类增加排除控件集合,在拖拽起始位置记录环节就做拦截,避免无效操作:
class Move():
    def __init__(self):
        self._x = 0
        self._y = 0
        # 新增排除控件集合
        self.excluded_widgets = set()
    def start_move2(self, event):
        # 如果触发事件的控件在排除列表中,直接返回不记录拖拽起始点
        if event.widget in self.excluded_widgets:
            return
        self._x = event.x
        self._y = event.y
    def stop_move2(self, event):
        self._x = None
        self._y = None
    def on_move2(self, event):
        # 加一层保险,避免起始点异常记录的情况
        if self._x is None or self._y is None or event.widget in self.excluded_widgets:
            return
        deltax = event.x - self._x
        deltay = event.y - self._y
        win = event.widget.winfo_toplevel()
        new_position = "+{}+{}".format(win.winfo_x() + deltax, win.winfo_y() + deltay)
        win.geometry(new_position) 
  1. 在A1类的open方法中,把需要排除的两个按钮加入排除集合:
    在创建完self._btn_1和self._btn_2后,添加两行代码:
# 将需要排除的控件加入集合
self.excluded_widgets.add(self._btn_1)
self.excluded_widgets.add(self._btn_2)

修改说明

  • 抛弃了原代码中硬编码winfo_parent路径的判断方式,直接对比控件实例,不管布局怎么调整都不会失效
  • 拦截逻辑放在移动操作执行之前,不会出现先移动再判断的无效操作
  • 后续需要新增排除控件,只需要往excluded_widgets集合里添加对应实例即可,拓展性极强

完整可运行代码

from tkinter import *

class Move():
    def __init__(self):
        self._x = 0
        self._y = 0
        self.excluded_widgets = set()
    def start_move2(self, event):        
        if event.widget in self.excluded_widgets:
            return
        self._x = event.x
        self._y = event.y
    def stop_move2(self, event):
        self._x = None
        self._y = None
    def on_move2(self, event):
        if self._x is None or self._y is None or event.widget in self.excluded_widgets:
            return
        deltax = event.x - self._x
        deltay = event.y - self._y
        win = event.widget.winfo_toplevel()

        new_position = "+{}+{}".format(win.winfo_x() + deltax, win.winfo_y() + deltay)
        win.geometry(new_position) 

class A1 (Frame, Move):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)
        self.master = master
        self.btn = Button(self, text='opens', command=self.open)
        self.btn.pack()

        self.bind_all("<ButtonPress-1>", self.start_move2)
        self.bind_all("<B1-Motion>", self.on_move2)
        self.bind_all("<ButtonRelease-1>", self.stop_move2)

    def open(self):
        self.w1 = Toplevel(self)
        self.w1.overrideredirect(1)
        self.w1.wm_attributes ('-topmost', True)        
        self.w2 = Toplevel(self)
        self.w2.overrideredirect(1)
        self.w2.wm_attributes ('-topmost', True) 

        self.w1.geometry('300x150')
        self.w2.geometry('300x150')

        self.frame_1 = Frame(self.w1, bg='green')
        self.label_1 = Label(self.frame_1, text='___windows 1___', bg='green2', width=50)
        self.btn_1 = Button(self.label_1, text='AAAAAAA')

        self._frame_1 = Frame(self.frame_1, bg='green')
        self._label_1 = Label(self._frame_1, text='windows 1', bg='green2', width=50)
        self._btn_1 = Button(self._label_1, text='button 2 - A')
        self._bbn_11 = Button(self._label_1, text='button 3 - A')

        self.frame_2 = Frame(self.w2, bg='green')
        self.label_2 = Label(self.frame_2, text='___windows 2___', bg='green2', width=50)
        self.btn_2 = Button(self.label_2, text='BBBBBBB')

        self._frame_2 = Frame(self.frame_2, bg='green')
        self._label_2 = Label(self._frame_2, text='windows 1', bg='green2', width=50)
        self._btn_2 = Button(self._label_2, text='button 2 - B')
        self._bbn_22 = Button(self._label_2, text='button 3 - B')

        # 添加排除控件
        self.excluded_widgets.add(self._btn_1)
        self.excluded_widgets.add(self._btn_2)

        self.frame_1.pack()
        self.label_1.pack()
        self.btn_1.pack()
        self._frame_1.pack()
        self._label_1.pack()
        self._btn_1.pack()
        self._bbn_11.pack()
        
        self.frame_2.pack()
        self.label_2.pack()
        self.btn_2.pack()
        self._frame_2.pack()
        self._label_2.pack()
        self._btn_2.pack()
        self._bbn_22.pack()

root = Tk()
app = A1(root, bg='black')
app.pack(side=BOTTOM, fill=BOTH)
root.mainloop()

内容的提问来源于stack exchange,提问作者Jackie Ck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 07:15:07