Search code examples
pythontkintertext

Disable default keyboard shortcuts for tkinter text element


I am making a basic code editor with tkinter in python, and I would like ctrl+/ to comment out the selected code. The problem is, ctrl+/ selects all the text in the element.

I would like to know if there is a way to disable or work around this, as well as other default shortcuts/bindings, such as ctrl+a?

Here is the code that I have so far:

import tkinter as tk
import ctypes


def comment_code() -> None:
   ## This does not change the selection range, however, when ctrl+/ is pressed, all the text is selected
   ## With other key combinations the problem does not occur
   
   ## Get the selection range
   selection = text.tag_ranges('sel')

   if not selection:  ## If there is no selection
      ## Todo: Code to comment out lines
      return
   else:
      ## Add '\*' and '*\' to the start and end of the selected text
      text.replace(selection[0], selection[1], f'\\* {text.selection_get()} *\\')


window = tk.Tk()

## Increase the scaling and the DPI for the window. Increasing the DPI makes the resolution higher but decreases the size of the window and increasing the scale increases the size of the window.
ctypes.windll.shcore.SetProcessDpiAwareness(2)
window.tk.call('tk', 'scaling', 1.9)

## Make the first row and column resize with the window
window.columnconfigure(0, weight=1)
window.rowconfigure(0, weight=1)

## Set the window's size and position
window.geometry('720x480+720+480')

## Create a text element
text = tk.Text()
text.grid(sticky='NSWE')

## Bind ctrl+/ to comment out code
text.bind('<Control-/>', lambda e: comment_code())

## Insert sample text
text.insert(1.0, 'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Odio delectus impedit consequatur laborum, ducimus cum perferendis iste sed officiis quis quisquam id cupiditate nemo nobis, qui ut mollitia iusto nulla.')

window.mainloop()

Solution

  • You can disable the system default handling by returning "break" from the bind callback:

    def comment_code() -> None:
       ## This does not change the selection range, however, when ctrl+/ is pressed, all the text is selected
       ## With other key combinations the problem does not occur
    
       ## Get the selection range
       selection = text.tag_ranges('sel')
    
       if not selection:  ## If there is no selection
          ## Todo: Code to comment out lines
          pass
       else:
          ## Add '\*' and '*\' to the start and end of the selected text
          text.replace(selection[0], selection[1], f'\\* {text.selection_get()} *\\')
       # disable system default handling
       return "break"