Home > Back-end >  Tkinter bind button work incorrectly when hovering
Tkinter bind button work incorrectly when hovering

Time:02-20

Why my Tkinter bind buttons work incorrectly? When I go on the start button with the mouse, about button will change! show image

This is my code:

import tkinter as tk


class Panel(tk.Tk):

    def __init__(self):
        super().__init__()

        # window config
        self.title('test')
        self.geometry('300x300')
        self.configure(bg='#2b2e37')
 
   
    def btns(self, x, y, text, bg, fg):
        def on_enter(ctx):
            self.btn['background'] = fg
            self.btn['foreground'] = bg
        def on_leave(ctx):
            self.btn['background'] = bg
            self.btn['foreground'] = fg

        
        self.btn = tk.Button(self, text=text, bg=bg, fg=fg, activebackground=fg, activeforeground=bg, border=0, width=42, height=2)
        self.btn.bind('<Enter>', on_enter)
        self.btn.bind('<Leave>', on_leave)
        self.btn.place(x=x, y=y)
        

if __name__ == '__main__':
    window = Panel()
    window.btns(0, 190, 'S T A R T', '#2b2e37', '#56fc03')
    window.btns(0, 230, 'A B O U T', '#2b2e37', '#f5ec42')
    window.mainloop()

I think it's for my oop code, I wrote this simply and worked correctly. Sorry for my bad English

CodePudding user response:

I fixed my code by writing separately for each button.

New code:

    def btns(self):
        def on_enter1(ctx):
            self.btn1['background'] = '#56fc03'
            self.btn1['foreground'] = '#2b2e37'
        def on_leave1(ctx):
            self.btn1['background'] = '#2b2e37'
            self.btn1['foreground'] = '#56fc03'
        def on_enter2(ctx):
            self.btn2['background'] = '#f5ec42'
            self.btn2['foreground'] = '#2b2e37'
        def on_leave2(ctx):
            self.btn2['background'] = '#2b2e37'
            self.btn2['foreground'] = '#f5ec42'

        
        self.btn1 = tk.Button(self, text='S T A R T', bg='#2b2e37', fg='#56fc03', activebackground='#56fc03', activeforeground='#2b2e37', border=0, width=42, height=2)
        self.btn2 = tk.Button(self, text='A B O U T', bg='#2b2e37', fg='#f5ec42', activebackground='#f5ec42', activeforeground='#2b2e37', border=0, width=42, height=2)
        self.btn1.bind('<Enter>', on_enter1)
        self.btn1.bind('<Leave>', on_leave1)
        self.btn2.bind('<Enter>', on_enter2)
        self.btn2.bind('<Leave>', on_leave2)
        self.btn1.place(x=0, y=190)
        self.btn2.place(x=0, y=230)

if __name__ == '__main__':
    window = Panel()
    window.label()
    window.btns()
    window.mainloop()

CodePudding user response:

The button on which the event occurs is passed to the event handlers in the ctx parameter in the widget attribute, so you can use that instead of self.btn:

    def btns(self, x, y, text, bg, fg):
        def on_enter(ctx):
            ctx.widget['background'] = fg
            ctx.widget['foreground'] = bg
        def on_leave(ctx):
            ctx.widget['background'] = bg
            ctx.widget['foreground'] = fg

The problem with using self.btn in place of ctx.widget in these event handlers is that the second time you call btns, self.btn is replaced with the second button, so the event handlers you added to the first button end up making changes to the second button.

  • Related