Discussion:
Tkinter menu item underline syntax
(too old to reply)
Rich Shepard
2021-01-06 18:32:58 UTC
Permalink
My application's menu has lines like this:
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline 0],
accelerator = 'Ctrl+N'
)

Python reports a syntax error when specifying the string index to underline;
it rejects both a space and an equals sign (=).

In "Modern Tkinter", page 88, the author explains,
"Underline
"While all platforms support keyboard traversal of the menubar via the arrow
keys, on Windows and X11, you can also use other keys to jump to particular
menus or menu items. The keys that trigger these jumps are indicated by an
underlined letter in the menu item’s label. If you want to add one of these
to a menu item, you can use the "underline" configuration option for the
item. The value of this option should be the index of the character you’d like
underlined (from 0 to the length of the string - 1)."

There is no example of the proper syntax and my web searches haven't found
one, either.

How do I pass a string index to the command to underline that character?

TIA,

Rich
Stefan Ram
2021-01-06 18:49:35 UTC
Permalink
Post by Rich Shepard
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline 0],
I don't know what your "self.callbacks" is, but
"underline=0" should be an argument of "add_command".

If you are still struggling with such elementary points,
you should go back to "Start" and learn the basics of Python
first (function call syntax, types of arguments, syntax of
the subscription with brackets) before you venture into
more advanced code with classes and tkinter.

There is no special syntax for tkinter.
2***@potatochowder.com
2021-01-06 19:08:55 UTC
Permalink
On 2021-01-06 at 10:32:58 -0800,
Post by Rich Shepard
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline 0],
accelerator = 'Ctrl+N'
)
Python reports a syntax error when specifying the string index to underline;
it rejects both a space and an equals sign (=).
I'm not a TKinter expert (nor even a current user), but that line that
begins with whitespace and "command =" looks suspicious. As far as I
can see, Python is correct to call it syntactically erroneous.

What is self.callbacks? Is it a function, a list of functions, a list
of something else?

Did you possibly mean to use parentheses "(" and ")" instead of brackets
"[" and "]"? Or perhaps some different punctuation between the "[" and
the "]"?
Post by Rich Shepard
From what I remember about TKinter, embedding Tcl/TK code inside strings
inside Python can be tricky (to say the least).

Sorry I don't have a concrete solution, just more to think about.
Rich Shepard
2021-01-06 19:18:15 UTC
Permalink
Post by 2***@potatochowder.com
I'm not a TKinter expert (nor even a current user), but that line that
begins with whitespace and "command =" looks suspicious. As far as I can
see, Python is correct to call it syntactically erroneous.
Yes, the line above it needed to be terminated by a comma, not \n.

I found the answer: underline is an option and options are key: value pairs.
So, the correct syntax is underline: 0.

Thanks,

Rich
2***@potatochowder.com
2021-01-06 20:03:50 UTC
Permalink
On 2021-01-06 at 11:18:15 -0800,
Post by Rich Shepard
Post by 2***@potatochowder.com
I'm not a TKinter expert (nor even a current user), but that line that
begins with whitespace and "command =" looks suspicious. As far as I can
see, Python is correct to call it syntactically erroneous.
Yes, the line above it needed to be terminated by a comma, not \n.
I found the answer: underline is an option and options are key: value pairs.
So, the correct syntax is underline: 0.
Glad you found it. :-)

For the sake of future generations who may run into this issue, can you
post the complete, correct call to file_menu.add_command?
Terry Reedy
2021-01-06 20:21:06 UTC
Permalink
        file_menu.add_command(
            label = 'New',
            command = self.callbacks['file->new', underline 0],
            accelerator = 'Ctrl+N'
        )
'underline' has nothing to do with looking up the command in
self.callbacks. It is a keyword parameter for the add_command method,
and is handled like all other values passed by name, and as you did for
the other arguments

file_menu.add_command(
label='New',
underline=0,
command=self.callbacks['file->new],
accelerator='Ctrl+N'
)

Note: PEP 8 style is no spaces around '=' used for keyword arguments.
Here is an example from idlelib.editor, 978.

menu.add_command(label=ulchars[i] + " " + file_name,
command=callback,
underline=0)
--
Terry Jan Reedy
Rich Shepard
2021-01-06 20:42:36 UTC
Permalink
Post by 2***@potatochowder.com
For the sake of future generations who may run into this issue, can you
post the complete, correct call to file_menu.add_command?
This is the working version of the stanza I initially posted:

file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline: 0],
accelerator = 'Ctrl+N'
)

The label line separated from the command with a comma. The underline option
is a key and separated from its value with a colon.

HTH,

Rich
Chris Angelico
2021-01-06 20:51:57 UTC
Permalink
Post by Rich Shepard
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline: 0],
accelerator = 'Ctrl+N'
)
The label line separated from the command with a comma. The underline option
is a key and separated from its value with a colon.
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.

ChrisA
Rich Shepard
2021-01-06 21:03:02 UTC
Permalink
Post by Chris Angelico
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.
ChrisA,

I'm always open to learning. There's no error generated ... yet the
application doesn' open so it's time to run it through pdb.

Regards,

Rich
Chris Angelico
2021-01-06 21:29:34 UTC
Permalink
Post by Rich Shepard
Post by Chris Angelico
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.
ChrisA,
I'm always open to learning. There's no error generated ... yet the
application doesn' open so it's time to run it through pdb.
Cool. Terry had something on the subject in the other thread; I think
that's a good place to start. (I don't know much about Tkinter, this
line of code just looked odd in general Python syntax.)

ChrisA
Rich Shepard
2021-01-06 22:09:44 UTC
Permalink
Post by Chris Angelico
Cool. Terry had something on the subject in the other thread; I think
that's a good place to start. (I don't know much about Tkinter, this line
of code just looked odd in general Python syntax.)
ChrisA,

It's been a long time since I wrote any Python code. Assignments have spaces
surrounding equal signs while values to options don't. I think I have the
code cleaned now.

Regards,

Rich
Grant Edwards
2021-01-06 21:03:58 UTC
Permalink
Post by Rich Shepard
Post by 2***@potatochowder.com
For the sake of future generations who may run into this issue, can you
post the complete, correct call to file_menu.add_command?
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline: 0],
accelerator = 'Ctrl+N'
)
I'm completely baffled by that. Can somebody explain how this
expression is evaluated?

self.callbacks['file->new', underline: 0]

It appears that the dict callbacks is being accessed with the key of
a tuple comprising a string and a slice.

Huh?
Terry Reedy
2021-01-06 21:17:55 UTC
Permalink
Post by Rich Shepard
Post by Chris Angelico
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.
ChrisA,
I'm always open to learning. There's no error generated ... yet the
application doesn' open so it's time to run it through pdb.
See my response, sent an hour ago, for how to use 'underline.
--
Terry Jan Reedy
Chris Angelico
2021-01-06 22:27:49 UTC
Permalink
Post by Grant Edwards
Post by Rich Shepard
Post by 2***@potatochowder.com
For the sake of future generations who may run into this issue, can you
post the complete, correct call to file_menu.add_command?
file_menu.add_command(
label = 'New',
command = self.callbacks['file->new', underline: 0],
accelerator = 'Ctrl+N'
)
I'm completely baffled by that. Can somebody explain how this
expression is evaluated?
self.callbacks['file->new', underline: 0]
It appears that the dict callbacks is being accessed with the key of
a tuple comprising a string and a slice.
Heh, you had to try it to make sure it was valid? Me too. Here's how
it's parsed:

self.callbacks[ # this bit's non-controversial
'file->new' # string literal
, # make tuple
underline: 0 # slice(underline, 0, None)
]

So it takes the name "underline", whatever that is, and it assumes you
want a slice from underline to zero. That's all the second dimension
of the indexing, where the first is a simple string literal.

ChrisA
Peter Otten
2021-01-07 10:26:56 UTC
Permalink
Post by Rich Shepard
Post by Chris Angelico
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.
ChrisA,
I'm always open to learning. There's no error generated ... yet the
application doesn' open so it's time to run it through pdb.
Spoiler: unless the name 'underline' is defined you get a NameError:

NameError: name 'underline' is not defined

If it is defined and self.callbacks is a dict you get a TypeError:

TypeError: unhashable type: 'slice'

because that's what a colon means in a context like

x[a:b]

From what you posted I would guess that underline is most likely a
keyword argument to the add_command() method:

file_menu.add_command(
label='New',
command=self.callbacks['file->new'],
underline=0,
accelerator='Ctrl+N'
)
Peter Otten
2021-01-07 10:36:51 UTC
Permalink
Post by Grant Edwards
I'm completely baffled by that. Can somebody explain how this
expression is evaluated?
self.callbacks['file->new', underline: 0]
It appears that the dict callbacks is being accessed with the key of
a tuple comprising a string and a slice.
Huh?
def __getitem__(self, index): return index
Post by Grant Edwards
c = C()
underline = 42
c["foo", underline: 0]
('foo', slice(42, 0, None))

The OP's code will most certainly fail at runtime ;)
Rich Shepard
2021-01-07 13:32:37 UTC
Permalink
Post by Peter Otten
NameError: name 'underline' is not defined
TypeError: unhashable type: 'slice'
because that's what a colon means in a context like
x[a:b]
The template I used for the menu doesn't scale to my application so I'm
re-writing it from scratch.

Thanks, all,

Rich
Terry Reedy
2021-01-07 01:44:45 UTC
Permalink
Post by Terry Reedy
Post by Rich Shepard
Post by Chris Angelico
Are you sure that this works? It's syntactically valid, but I don't
think it means what you think it does.
ChrisA,
I'm always open to learning. There's no error generated ... yet the
application doesn' open so it's time to run it through pdb.
See my response, sent an hour ago, for how to use 'underline.
Reposting:

'underline' has nothing to do with looking up the command in
self.callbacks. It is a keyword parameter for the add_command method,
and is handled like all other values passed by name, and as you did for
the other arguments

file_menu.add_command(
label='New',
underline=0,
command=self.callbacks['file->new],
accelerator='Ctrl+N'
)

Note: PEP 8 style is no spaces around '=' used for keyword arguments.
Here is an example from idlelib.editor, 978.

menu.add_command(label=ulchars[i] + " " + file_name,
command=callback,
underline=0)
--
Terry Jan Reedy
Rich Shepard
2021-01-07 15:56:07 UTC
Permalink
Post by Terry Reedy
'underline' has nothing to do with looking up the command in
self.callbacks. It is a keyword parameter for the add_command method, and
is handled like all other values passed by name, and as you did for the
other arguments
file_menu.add_command(
label='New',
underline=0,
command=self.callbacks['file->new],
accelerator='Ctrl+N'
)
Note: PEP 8 style is no spaces around '=' used for keyword arguments. Here
is an example from idlelib.editor, 978.
menu.add_command(label=ulchars[i] + " " + file_name,
command=callback,
underline=0)
Thank you for the clarification.

Rich

Loading...