Как я могу обусловить активацию события привязки («») к определенной области окна?

#python #tkinter

Вопрос:

 class Right(Frame):
    def __init__(self, master, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.master.bind('<Enter>',self.mouse)
        self.master.bind('<Leave>',self.inmouse)
        self.lbl_77 = Label(self, text= 'Hellow', bg= 'green', fg='black')

    def mouse(self, event): 
        self.lbl_77 .place(x=90, y=0)
    def inmouse(self, event):
        self.lbl_77 .place_forget()

root = Tk()
frame = Right(root)
root.mainloop()
 

Что я попытался сделать с помощью кода, приведенного выше, так это сделать метку с сообщением «привет» видимой только тогда, когда указатель мыши находится на окне, и удалить ее, когда она его покидает. Мой вопрос в том, могу ли я разграничить область, которую нужно разделить на окно, так, чтобы только в том случае, если она лежит на нем, активировалось событие отображения метки.

Ответ №1:

Итак, вот подход, он использует <Motion> событие для отслеживания движения мыши, а также возвращает объект движения, который имеет атрибуты x и y который позволяет определить, где в данный момент находится мышь:

         self.master.bind('<Motion>', self.mouse)
        self.lbl_77 = Label(self, text='Hellow', bg='green', fg='black')

    def mouse(self, event):
        x, y = event.x, event.y
        x1, x2 = 0, 50
        y1, y2 = 0, 50
        if x1 < x < x2 and y1 < y < y2:
            self.lbl_77.place(x=90, y=0)
        else:
            self.lbl_77.place_forget()
 

Тогда дело в том, чтобы просто установить границы того, где проверять наличие мыши, и использовать простую if statement . Полный код будет выглядеть следующим образом:

 from tkinter import Tk, Frame, Label


class Right(Frame):
    def __init__(self, master, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.master.bind('<Motion>', self.mouse)
        self.lbl_77 = Label(self, text='Hellow', bg='green', fg='black')

    def mouse(self, event):
        x, y = event.x, event.y
        x1, x2 = 0, 50
        y1, y2 = 0, 50
        if x1 < x < x2 and y1 < y < y2:
            self.lbl_77.place(x=90, y=0)
        else:
            self.lbl_77.place_forget()


root = Tk()
root.geometry('500x500')
frame = Right(root)
frame.pack(fill='both', expand=True)
root.mainloop()
 

Несколько других деталей-это .pack() (или .grid() ) рамка, чтобы она расширилась и заполнила максимальную площадь (потому что вы используете .place() ), также, вероятно, установите геометрию окна на что-то, чтобы вам не пришлось изменять размер самостоятельно.

Импорт предложение:
я настоятельно не рекомендуем использовать подстановочный знак ( * ) при импорте что-то, вы должны либо импортировать то, что вам нужно, например, from module import Class1, func_1, var_2 и так далее, либо импортировать весь модуль: import module вы также можете использовать псевдоним: import module as md или sth, как это, дело в том, что не все импортное, если вы на самом деле знаете, что Вы делаете; наименование столкновения эту проблему.

Предложение PEP 8:
Я настоятельно рекомендую следовать руководству по стилю PEP 8 для кода Python. Имена функций и переменных должны быть в snake_case , имена классов в CapitalCase . Не используйте пробел, = если он используется как часть аргумента ключевого слова ( func(arg='value') ), но используйте пробел, = если он используется для присвоения значения ( variable = 'some value' ). Есть пространство вокруг операторов ( -/ и т.д.: value = x y (кроме здесь value = x y )). Есть две пустые строки вокруг объявлений функций и классов.

Комментарии:

1. Спасибо вам за ваш ответ и предложение. Ваш ответ разрешил вопрос, который я задал. Хотя код четко определен, он приносит с собой новые вопросы. Я надеюсь, что кто-нибудь сможет мне ответить. Спасибо. <Motion> проблема решена, но при быстром удалении указателя мыши из окна (область активации) метка все еще видна.

2. Мне приходит в голову использовать функцию: after и` DoubleVar` для обновления event.x , но она плохо работает self.master.bind ('<Button-1>', self.return) , потому def return (self ) что постоянно позиционирует метку при нажатии на ту же область триггера event.x , и, похоже, возникает конфликт между event.x и` self.return`. потому что этикетка мигает

3. Я понимаю, что метка останется, если вы быстро переместите курсор полностью за пределы окна? Хорошо привяжите '<Leave>' событие, которое будет просто .place_forget() self : self.bind('<Leave>', lamda e: self.lbl_77.place_forget())

4. Это отлично сработало, спасибо. Привязка <Leave> события к рамке, а не к родительскому окну работала нормально.