user8116739
user8116739

Reputation:

Getting a _tkinter.TclError when I try to cut and paste in a custom tkinter text field

I am working on a text editor using tkinter in python 3. I am having an issue with the custom text field class that I am using to attatch line numbers. It is from the answer from Brian Oakley to this question. Here is the code for the class:

class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, *args):
        # let the actual widget perform the requested action
        cmd = (self._orig,) + args
        result = self.tk.call(cmd)

        # generate an event if something was added or deleted,
        # or the cursor position changed
        if (args[0] in ("insert", "replace", "delete") or 
            args[0:3] == ("mark", "set", "insert") or
            args[0:2] == ("xview", "moveto") or
            args[0:2] == ("xview", "scroll") or
            args[0:2] == ("yview", "moveto") or
            args[0:2] == ("yview", "scroll")
        ):
            self.event_generate("<<Change>>", when = "tail")

        # return what the actual widget returned
        return result

Here is the code for the cut function:

def cutSelected(event=None):
    textField.event_generate("<<Cut>>")

...

# Add cut to the edit menu in the menu bar
editMenu.add_command(label = "Cut", command = cutSelected, accelerator = "Ctrl+X")

...

# setting up the keyboard shortcut for the cut function
textField.bind("<Control-x>", cutSelected)
textField.bind("<Control-X>", cutSelected)

Here is the code for the paste function:

def paste(event=None):
    textField.event_generate("<<Paste>>")

...

# Add paste to the edit menu in the menu bar
editMenu.add_command(label = "Paste", command = paste, accelerator = "Ctrl+V")

...

# setting up the keyboard shortcut for the paste function
textField.bind("<Control-v>", paste)
textField.bind("<Control-V>", paste)

Here is the error traceback (except for the credentials from the paths):

Traceback (most recent call last):
  File "C:\Users\me\mydocuments\Programming\myeditor\main.py", line 457, in <module>
    root.mainloop()
  File "C:\Users\me\AppData\Local\Programs\Python\Python37- 
32\lib\tkinter\__init__.py", line 1283, in mainloop
    self.tk.mainloop(n)
  File "C:\Users\me\mydocuments\Programming\myeditor\main.py", line 58, in _proxy
    result = self.tk.call(cmd)
_tkinter.TclError: text doesn't contain any characters tagged with "sel"

When I try to paste the text via the keyboard shortcut, it doesn't give me an error, it just pastes my text twice on the same line. (ex: test gets pasted as testtest) but when I do it via the edit menu in the menu bar, I get the error shown above.

Cut works just fine when I do it from the edit menu but when I try to cut text via the keyboard shortcut, I get the error.

I have been trying to fix these issues for almost a week now and the closest that I have come to an answer was from this question on stack overrun. I tried that code and had the exact same problem. I am not sure what else to do so any help at all is greatly appreciated.

Upvotes: 1

Views: 701

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385970

_tkinter.TclError: text doesn't contain any characters tagged with "sel"

I don't think I have a proper fix, but I have something that prevents your code from crashing.

Replace this:

result = self.tk.call(cmd)

... with this:

try:
    result = self.tk.call(cmd)
except Exception:
    return None

It may mask other things that should legitimately throw an error, but at the moment it's the best solution I have.

When I try to paste the text via the keyboard shortcut, it doesn't give me an error, it just pastes my text twice on the same line.

It's probably doing it twice because tkinter already has a default binding for cut and paste. What's probably happening is that your binding is firing and then the built-in binding is firing. If you want to prevent the built-in binding from taking effect you need to return "break" from paste. I'm only guessing at this point since you didn't provide a [mcve] for that.

Upvotes: 2

Related Questions