Re: Navigation in menu with multiple columns

Vasilis Vlachoudis <[email protected]> Mon, 18 Sep 2023 07:42:23 +0000
Newsgroups gmane.comp.python.tkinter
Message-ID <ZRAP278MB0221BE790B00F0290E9BD60084FBA@ZRAP278MB0221.CHEP278.PROD.OUTLOOK.COM>
--===============4501436502608946428==
Content-Language: en-IE
Content-Type: multipart/alternative;
	boundary="_000_ZRAP278MB0221BE790B00F0290E9BD60084FBAZRAP278MB0221CHEP_"

--_000_ZRAP278MB0221BE790B00F0290E9BD60084FBAZRAP278MB0221CHEP_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Great, many thanks Michael!
________________________________
From: Michael Lange <[email protected]>
Sent: Sunday 17 September 2023 02:14
To: Vasilis Vlachoudis <[email protected]>
Cc: [email protected] <[email protected]>
Subject: Re: [Tkinter-discuss] Navigation in menu with multiple columns

Hi Vasilis,

On Fri, 15 Sep 2023 09:55:49 +0000
Vasilis Vlachoudis <[email protected]> wrote:

> Hi Michael,
>
> here is a snipped of a code and what I've managed up to now

thanks, I get your point now :-)

I toyed around with your example a bit and came up with a custom menu
class (see below; for testing I added a few useless separators and another
submenu to the demo code). It's far from being perfect, but at least the
keyboard navigation appears to work (It might require more thorough
testing, though. Separators appear to be especially tricky.). Just for the
fun of it I also added keybindings for the PageUp, PageDown, Home and End
keys, which I thought might come in handy when dealing with huge submenus.

Have a nice day,

Michael

################################################################

import tkinter

class GriddedMenu(tkinter.Menu):
    '''Menu with lots of menu items arranged in a grid.'''
    # TODO: insert(), delete(), add_cascade(), add_checkbutton(),
    # add_radiobutton(), add_separator(), configure()
    def __init__(self, parent, numrows=3D20, **kw):
        tkinter.Menu.__init__(self, parent, **kw)
        self.numrows =3D numrows
        self._curindex =3D -1
        if self.type(0) =3D=3D 'tearoff':
            self._curindex =3D 0
        self.bind("<Right>", self._on_key_right)
        self.bind("<Left>", self._on_key_left)
        self.bind("<Prior>", self._on_key_pageup)
        self.bind("<Next>", self._on_key_pagedown)
        self.bind("<Home>", self._on_key_home)
        self.bind("<End>", self._on_key_end)

    def add_cascade(self, **kw):
        # FIXME: handle columnbreaks
        tkinter.Menu.add_cascade(self, **kw)
        self._curindex +=3D 1

    def add_command(self, **kw):
        tkinter.Menu.add_command(self, **kw)
        self._curindex +=3D 1
        if (self._curindex >=3D self.numrows) and \
                                (self._curindex % self.numrows =3D=3D 0):
            self.entryconfigure(self._curindex, columnbreak=3D1)

    def add_separator(self, **kw):
        # FIXME: handle columnbreaks
        tkinter.Menu.add_separator(self, **kw)
        self._curindex +=3D 1

    def _on_key_left(self, event):
        index =3D self.index('active')
        if index - self.numrows >=3D 0:
            newindex =3D index - self.numrows
            while (newindex >=3D 0) and (self.type(newindex) =3D=3D 'separa=
tor'):
                newindex -=3D self.numrows
            if newindex >=3D 0:
                self.activate(newindex)
            return 'break'

    def _on_key_right(self, event):
        index =3D self.index('active')
        end =3D self.index('end')
        if index + self.numrows <=3D end:
            newindex =3D index + self.numrows
            while (newindex <=3D end) and (self.type(newindex) =3D=3D 'sepa=
rator'):
                newindex +=3D self.numrows
            if newindex <=3D end:
                self.activate(newindex)
            return 'break'

    def _on_key_pageup(self, event):
        index =3D self.index('active')
        row =3D index % self.numrows
        newindex =3D index - row
        while self.type(newindex) =3D=3D 'separator':
            newindex +=3D 1
        self.activate(newindex)

    def _on_key_pagedown(self, event):
        index =3D self.index('active')
        row =3D index % self.numrows
        newindex =3D min(self.index('end'), index + (self.numrows - row - 1=
))
        while self.type(newindex) =3D=3D 'separator':
            newindex -=3D 1
        self.activate(newindex)

    def _on_key_home(self, event):
        newindex =3D 0
        while self.type(newindex) =3D=3D 'separator':
            newindex +=3D 1
        self.activate(newindex)

    def _on_key_end(self, event):
        newindex =3D self.index('end')
        while self.type(newindex) =3D=3D 'separator':
            newindex -=3D 1
        self.activate(newindex)

#--------------------------------------------------------------------------=
----

if __name__ =3D=3D "__main__":

    def show_menu(event):
        menu =3D tkinter.Menu(tearoff=3D0)
        for label in ["one","two","three","four"]:
            submenu =3D GriddedMenu(menu)
            menu.add_cascade(label=3Dlabel, menu=3Dsubmenu)
            for i in range(8):
                submenu.add_command(label=3Df"Item #{i}")
            submenu.add_separator()
            for i in range(8, 57):
                submenu.add_command(label=3Df"Item #{i}")
            submenu.add_separator()
            for i in range(57, 72):
                submenu.add_command(label=3Df"Item #{i}")
            submenu.add_separator()
            for i in range(72, 101):
                submenu.add_command(label=3Df"Item #{i}")
            submenu.add_separator()
            subsubmenu =3D tkinter.Menu(submenu)
            submenu.add_cascade(label=3D'foo', menu=3Dsubsubmenu)
            subsubmenu.add_command(label=3D'bar')
            submenu.add_separator()
        menu.tk_popup(event.x_root, event.y_root)

    root =3D tkinter.Tk()
    tkinter.Label(root, text=3D"<1> Left click to show menu").pack()
    tkinter.Label(root, text=3D"<q> to exit").pack()
    root.bind("<1>", show_menu)
    root.bind("<Key-q>", lambda e: root.destroy())
    root.mainloop()

###########################################################################=
####

--_000_ZRAP278MB0221BE790B00F0290E9BD60084FBAZRAP278MB0221CHEP_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
>
<style type=3D"text/css" style=3D"display:none;"> P {margin-top:0;margin-bo=
ttom:0;} </style>
</head>
<body dir=3D"ltr">
<div style=3D"font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, =
Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" clas=
s=3D"elementToProof">
Great, many thanks Michael!</div>
<div id=3D"appendonsend"></div>
<hr style=3D"display:inline-block;width:98%" tabindex=3D"-1">
<div id=3D"divRplyFwdMsg" dir=3D"ltr"><font face=3D"Calibri, sans-serif" st=
yle=3D"font-size:11pt" color=3D"#000000"><b>From:</b> Michael Lange &lt;kla=
[email protected]&gt;<br>
<b>Sent:</b> Sunday 17 September 2023 02:14<br>
<b>To:</b> Vasilis Vlachoudis &lt;[email protected]&gt;<br>
<b>Cc:</b> [email protected] &lt;[email protected]&gt;<br=
>
<b>Subject:</b> Re: [Tkinter-discuss] Navigation in menu with multiple colu=
mns</font>
<div>&nbsp;</div>
</div>
<div class=3D"BodyFragment"><font size=3D"2"><span style=3D"font-size:11pt;=
">
<div class=3D"PlainText">Hi Vasilis,<br>
<br>
On Fri, 15 Sep 2023 09:55:49 +0000<br>
Vasilis Vlachoudis &lt;[email protected]&gt; wrote:<br>
<br>
&gt; Hi Michael,<br>
&gt;<br>
&gt; here is a snipped of a code and what I've managed up to now<br>
<br>
thanks, I get your point now :-)<br>
<br>
I toyed around with your example a bit and came up with a custom menu<br>
class (see below; for testing I added a few useless separators and another<=
br>
submenu to the demo code). It's far from being perfect, but at least the<br=
>
keyboard navigation appears to work (It might require more thorough<br>
testing, though. Separators appear to be especially tricky.). Just for the<=
br>
fun of it I also added keybindings for the PageUp, PageDown, Home and End<b=
r>
keys, which I thought might come in handy when dealing with huge submenus.<=
br>
<br>
Have a nice day,<br>
<br>
Michael<br>
<br>
################################################################<br>
<br>
import tkinter<br>
<br>
class GriddedMenu(tkinter.Menu):<br>
&nbsp;&nbsp;&nbsp; '''Menu with lots of menu items arranged in a grid.'''<b=
r>
&nbsp;&nbsp;&nbsp; # TODO: insert(), delete(), add_cascade(), add_checkbutt=
on(),<br>
&nbsp;&nbsp;&nbsp; # add_radiobutton(), add_separator(), configure()<br>
&nbsp;&nbsp;&nbsp; def __init__(self, parent, numrows=3D20, **kw):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tkinter.Menu.__init__(self, pare=
nt, **kw)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.numrows =3D numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._curindex =3D -1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.type(0) =3D=3D 'tearoff'=
:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._cu=
rindex =3D 0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;Right&gt;&qu=
ot;, self._on_key_right)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;Left&gt;&quo=
t;, self._on_key_left)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;Prior&gt;&qu=
ot;, self._on_key_pageup)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;Next&gt;&quo=
t;, self._on_key_pagedown)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;Home&gt;&quo=
t;, self._on_key_home)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.bind(&quot;&lt;End&gt;&quot=
;, self._on_key_end)<br>
<br>
&nbsp;&nbsp;&nbsp; def add_cascade(self, **kw):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # FIXME: handle columnbreaks<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tkinter.Menu.add_cascade(self, *=
*kw)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._curindex +=3D 1<br>
<br>
&nbsp;&nbsp;&nbsp; def add_command(self, **kw):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tkinter.Menu.add_command(self, *=
*kw)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._curindex +=3D 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (self._curindex &gt;=3D self.=
numrows) and \<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (self._curindex % self.numrows =3D=3D =
0):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.ent=
ryconfigure(self._curindex, columnbreak=3D1)<br>
<br>
&nbsp;&nbsp;&nbsp; def add_separator(self, **kw):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # FIXME: handle columnbreaks<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tkinter.Menu.add_separator(self,=
 **kw)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._curindex +=3D 1<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_left(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index =3D self.index('active')<b=
r>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if index - self.numrows &gt;=3D =
0:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 =3D index - self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (n=
ewindex &gt;=3D 0) and (self.type(newindex) =3D=3D 'separator'):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; newindex -=3D self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if newin=
dex &gt;=3D 0:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; self.activate(newindex)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return '=
break'<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_right(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index =3D self.index('active')<b=
r>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end =3D self.index('end')<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if index + self.numrows &lt;=3D =
end:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 =3D index + self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (n=
ewindex &lt;=3D end) and (self.type(newindex) =3D=3D 'separator'):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; newindex +=3D self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if newin=
dex &lt;=3D end:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; self.activate(newindex)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return '=
break'<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_pageup(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index =3D self.index('active')<b=
r>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; row =3D index % self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex =3D index - row<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while self.type(newindex) =3D=3D=
 'separator':<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 +=3D 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.activate(newindex)<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_pagedown(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index =3D self.index('active')<b=
r>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; row =3D index % self.numrows<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex =3D min(self.index('end=
'), index + (self.numrows - row - 1))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while self.type(newindex) =3D=3D=
 'separator':<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 -=3D 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.activate(newindex)<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_home(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex =3D 0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while self.type(newindex) =3D=3D=
 'separator':<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 +=3D 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.activate(newindex)<br>
<br>
&nbsp;&nbsp;&nbsp; def _on_key_end(self, event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex =3D self.index('end')<b=
r>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while self.type(newindex) =3D=3D=
 'separator':<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newindex=
 -=3D 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.activate(newindex)<br>
<br>
#--------------------------------------------------------------------------=
----<br>
<br>
if __name__ =3D=3D &quot;__main__&quot;:<br>
<br>
&nbsp;&nbsp;&nbsp; def show_menu(event):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; menu =3D tkinter.Menu(tearoff=3D=
0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for label in [&quot;one&quot;,&q=
uot;two&quot;,&quot;three&quot;,&quot;four&quot;]:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu =
=3D GriddedMenu(menu)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; menu.add=
_cascade(label=3Dlabel, menu=3Dsubmenu)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in=
 range(8):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; submenu.add_command(label=3Df&quot;Item #{i}&quot;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_separator()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in=
 range(8, 57):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; submenu.add_command(label=3Df&quot;Item #{i}&quot;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_separator()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in=
 range(57, 72):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; submenu.add_command(label=3Df&quot;Item #{i}&quot;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_separator()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in=
 range(72, 101):<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp; submenu.add_command(label=3Df&quot;Item #{i}&quot;)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_separator()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subsubme=
nu =3D tkinter.Menu(submenu)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_cascade(label=3D'foo', menu=3Dsubsubmenu)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subsubme=
nu.add_command(label=3D'bar')<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; submenu.=
add_separator()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; menu.tk_popup(event.x_root, even=
t.y_root)<br>
<br>
&nbsp;&nbsp;&nbsp; root =3D tkinter.Tk()<br>
&nbsp;&nbsp;&nbsp; tkinter.Label(root, text=3D&quot;&lt;1&gt; Left click to=
 show menu&quot;).pack()<br>
&nbsp;&nbsp;&nbsp; tkinter.Label(root, text=3D&quot;&lt;q&gt; to exit&quot;=
).pack()<br>
&nbsp;&nbsp;&nbsp; root.bind(&quot;&lt;1&gt;&quot;, show_menu)<br>
&nbsp;&nbsp;&nbsp; root.bind(&quot;&lt;Key-q&gt;&quot;, lambda e: root.dest=
roy())<br>
&nbsp;&nbsp;&nbsp; root.mainloop()<br>
<br>
###########################################################################=
####<br>
</div>
</span></font></div>
</body>
</html>

--_000_ZRAP278MB0221BE790B00F0290E9BD60084FBAZRAP278MB0221CHEP_--

--===============4501436502608946428==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Tkinter-discuss mailing list
[email protected]
https://mail.python.org/mailman/listinfo/tkinter-discuss

--===============4501436502608946428==--