[Tkinter-discuss] Button-press on Menubuttons

Michael Lange klappnase at web.de
Sun Nov 27 12:12:48 CET 2011

Thus spoketh Cam Farnell <msa01 at bitflipper.ca> 
unto us on Sat, 26 Nov 2011 15:54:51 -0400:

> Thanks, using the postcommand option does the job but it still strikes
> me as odd that a menubutton which has been been activated by clicking
> on it doesn't generate a <ButtonPress> event.

Now, I guess what actually happens is this:

when Menu A is being mapped it does a grab_set_global() behind the
scenes, which is useful, because it needs to be aware if the user clicks
for example on the desktop and as a consequence of this the menu must be
unmapped. There is no other way for tk to know this than the global grab.
Now when you click Menubutton B with Menu A still being mapped, the
ButtonPress event is actually being grabbed by Menu A.

Right now I can see the same behavior if I run your test app on top of
my mail client's window: when I click into the mail client while
Menu A is mapped, the menu disappears but the test app stays on top of
the mail client, which is perfectly normal in this context, it would be
confusing if the test app would be hidden under the other window on the
first mouse click when I just want to "click away" the menu. It seems
like it is exactly the same which now confuses you; probably the tk
developers decided that it's better to confuse programmers than users ;)

Maybe what happens becomes clearer if you add a few additional
callbacks with print statements to your example :

import Tkinter as tk

class Application(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)

        self.MenuButtonA = tk.Menubutton(self,text='Menu Button A')
        self.TA = TA = tk.Menu(self.MenuButtonA)
        TA.add_command(label='Dummy 1')
        TA.add_command(label='Dummy 2')
        self.MenuButtonA['menu'] = TA
        self.MenuButtonA.bind('<ButtonPress-1>',self.HandlerA, '+')
        TA.bind('<Map>', self.on_map_A, '+')
        TA.bind('<Unmap>', self.on_unmap_A, '+')
        self.MenuButtonA.bind('<ButtonPress-1>',self.on_b1_A, '+')
        self.MenuButtonA.bind('<ButtonRelease-1>',self.on_b1release_A, '+')

        self.MenuButtonB = tk.Menubutton(self,text='Menu Button B')
        self.TB = TB = tk.Menu(self.MenuButtonB)
        TB.add_command(label='Dummy 1')
        TB.add_command(label='Dummy 2')
        self.MenuButtonB['menu'] = TB
        self.MenuButtonB.bind('<ButtonPress-1>',self.HandlerB, '+')
        TB.bind('<Map>', self.on_map_B, '+')
        TB.bind('<Unmap>', self.on_unmap_B, '+')
        self.MenuButtonB.bind('<ButtonPress-1>',self.on_b1_B, '+')
        self.MenuButtonB.bind('<ButtonRelease-1>',self.on_b1release_B, '+')

        self.InfoLabel = tk.Label(self,text='---------')

    def HandlerA(self,Event=None):
        self.InfoLabel['text'] = 'Handler A'
        print 'Handler A'
        self.TA.entryconfigure(1, label='FOO')

    def HandlerB(self,Event=None):
        self.InfoLabel['text'] = 'Handler B'
        print 'Handler B'
        self.TB.entryconfigure(1, state='disabled')

    def on_b1_A(self, event):
        print 'button 1 pressed over Menubutton A'

    def on_b1release_A(self, event):
        print 'button 1 released over Menubutton A'

    def on_b1_B(self, event):
        print 'button 1 pressed over Menubutton B'

    def on_b1release_B(self, event):
        print 'button 1 released over Menubutton B'

    def on_map_A(self, event):
        print 'Menu A mapped'

    def on_map_B(self, event):
        print 'Menu B mapped'

    def on_unmap_A(self, event):
        print 'Menu A unmapped'

    def on_unmap_B(self, event):
        print 'Menu B unmapped'

app = Application()
app.master.title("Sample application")


When you run this, you see that while Menu A is mapped the button press
event never reaches Menubutton B.

Best regards


.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

It [being a Vulcan] means to adopt a philosophy, a way of life which is
logical and beneficial.  We cannot disregard that philosophy merely for
personal gain, no matter how important that gain might be.
		-- Spock, "Journey to Babel", stardate 3842.4

More information about the Tkinter-discuss mailing list