python-3.xtkinterkeyboard-shortcutskeyboard-eventstkinter-menu

Is there a way to add a check button to a tkinter menu when a keyboard event occurs?


I have a checkbox toolbar menu option in tkinter. Whenever, I click on the option, it enables word wrap and puts a check mark next to it.

# Toggle Word Wrap Function
def ToggleWordWrap(*args):
    # If there is no word wrap then add word wrap
    if TextBox.cget("wrap") == "none":
        TextBox.configure(wrap="word")
    # If there is word wrap then take out word wrap
    elif TextBox.cget("wrap") == "word":
        TextBox.configure(wrap="none")

# Check Marks for Options in Tools Menu
WordWrap_CheckMark = BooleanVar()
WordWrap_CheckMark.set(False)

# Tools Option for Menu Bar
ToolsOption = Menu(MenuBar, tearoff=False)
MenuBar.add_cascade(label="Tools", menu=ToolsOption, underline=0)
ToolsOption.add_command(label="Word Count")
ToolsOption.add_checkbutton(label="Toggle Word Wrap", onvalue=1, offvalue=0, variable=WordWrap_CheckMark, command=ToggleWordWrap)

I also decided that I should add a keyboard binding Alt-Z to the function.

# Toggle Word Wrap Function
def ToggleWordWrap(*args):
    # If there is no word wrap then add word wrap
    if TextBox.cget("wrap") == "none":
        TextBox.configure(wrap="word")
    # If there is word wrap then take out word wrap
    elif TextBox.cget("wrap") == "word":
        TextBox.configure(wrap="none")
root.bind("<Alt-Key-z>", ToggleWordWrap)

# Check Marks for Options in Tools Menu
WordWrap_CheckMark = BooleanVar()
WordWrap_CheckMark.set(False)

# Tools Option for Menu Bar
ToolsOption = Menu(MenuBar, tearoff=False)
MenuBar.add_cascade(label="Tools", menu=ToolsOption, underline=0)
ToolsOption.add_command(label="Word Count")
ToolsOption.add_checkbutton(label="Toggle Word Wrap", onvalue=1, offvalue=0, variable=WordWrap_CheckMark, command=ToggleWordWrap, accelerator="Alt-Z")

Whenever I use the keyboard binding, it does not turn the check mark on. How would I fix this?


Solution

  • you need to set WordWrap_CheckMark True when word-wrap is on.

    Here is your function:

    def toggleWordWrap(event=None):
       
       if textBox.cget("wrap") == "none":
            textBox.configure(wrap="word")
            WordWrap_CheckMark.set(True)
        # If there is word wrap then take out word wrap
    
       elif textBox.cget("wrap") == "word":
            textBox.configure(wrap="none")
            WordWrap_CheckMark.set(False)
    

    Here is the full example:

    from tkinter import *
    
    def toggleWordWrap(event=None):
       
       if textBox.cget("wrap") == "none":
            textBox.configure(wrap="word")
            WordWrap_CheckMark.set(True)
        # If there is word wrap then take out word wrap
    
       elif textBox.cget("wrap") == "word":
            textBox.configure(wrap="none")
            WordWrap_CheckMark.set(False)
    
    root = Tk()
    
    root.bind_all("<Alt-Key-z>", toggleWordWrap)  # just Alt-z will also work fine
    
    WordWrap_CheckMark = BooleanVar()
    WordWrap_CheckMark.set(False)
    
    menuBar = Menu(root)
    
    tools = Menu(menuBar, tearoff=0)
    tools.add_command(label='Word Count')
    tools.add_checkbutton(label="Toggle Word Wrap", onvalue=1, offvalue=0, variable=WordWrap_CheckMark, command=toggleWordWrap, accelerator="Alt-Z")
    
    menuBar.add_cascade(label ='Tools', menu=tools)
    
    textBox = Text(root, wrap="none")
    textBox.pack()
    
    root.config(menu = menuBar)
    root.mainloop()