如果我全局使用 bind_all,我可以为某些小部件设置例外吗?

if I use bind_all globally, can I make exceptions for some widgets?

我将在我的代码中详细说明最相关的数据,我打算找到一种有效的方法来进行排除小部件的检查,在这种情况下它将是 self._btn_1self._btn_2

  1. 此应用程序所做的是创建两个 windows 没有 window 管理器,您可以通过单击任意位置拖动鼠标来移动 windows。
  2. 为了演示我的脚本的真实结构,所提供代码的结构被夸大了。

这个函数链接到整个应用程序,负责移动windows。这就是验证应该进行的地方,正如您在最后一部分中看到的那样,这就是我想到的进行验证的方式,以便在拖动鼠标时 window 不会移动。谢谢。

def on_move2(self, event):
        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) 

        #print('print:', event.widget.winfo_parent())
        if event.widget.winfo_parent() == '.!a1.!toplevel.!frame.!frame.!label':
            print('You found me but you have 0')

完整的脚本从这里开始。

from tkinter import *

class Move():
    def __init__(self):
        self._x = 0
        self._y = 0
    def start_move2(self, event):        
        self._x = event.x
        self._y = event.y
    def stop_move2(self, event):
        self._x = None
        self._y = None
    def on_move2(self, event):
        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) 

        #print('print:', event.widget.winfo_parent())
        if event.widget.winfo_parent() == '.!a1.!toplevel.!frame.!frame.!label':
            print('You found me but you have 0')
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.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()

如果您想排除特定的小部件,可以说最简单的解决方案是将该小部件添加到列表中,然后将 event.widget 与该列表进行比较。

首先扩展 Move class 以获得不可移动的小部件列表、将小部件添加到列表的方法以及确定小部件是否可移动的方法。

class Move():
    def __init__(self):
        ...
        self._unmovable = []
        
    def make_unmovable(self, *widgets):
        self._unmovable.extend(widgets)
        
    def _is_movable(self, widget):
        return widget not in self._unmovable
    ...

然后,您可以在创建时将小部件添加到不可移动列表中,并在处理事件时检查它们是否在列表中。

def on_move2(self, event):
    if not self._is_movable(event.widget):
        return
    ...

您需要确保在 A1 中调用了 Move.__init__

class A1 (Frame, Move):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)
        Move.__init__(self)
        ...

最后,将您不想移动的小部件添加到列表中:

class A1 (Frame, Move):
    ...
    def open(self):
        ...
        self._btn_1 = Button(self._label_1, text='button 2 - A')   #
        self._btn_2 = Button(self._label_2, text='button 2 - B')
        ...
        self.make_unmovable(self._btn_1, self._btn_2)