Adding a built-in functionality

Tkinter's Text widget comes with some handy built-in functionalities to handle common text-related functions. Let's leverage these functionalities to implement some common features in the text editor.

Let's start by implementing the cut, copy, and paste features. We now have the editor GUI ready. If you open the program and play with the Text widget, you will see that you can perform basic functions such as cut, copy, and paste in the text area by using Ctrl + X, Ctrl + C, and Ctrl + V, respectively. All of these functions exist without us having to add a single line of code for these functionalities.

The Text widget clearly comes with these built-in events. Now, we simply want to connect these events to their respective menu items.

The documentation of the Tcl/Tk universal widget methods tells us that we can trigger events without an external stimulus by using the following command:

widget.event_generate(sequence, **kw)

To trigger the Cut event, all we need is the following line in the code:

content_text.event_generate("<<Cut>>")

Let's call it by using a cut function and associate it with the Cut menu by using the callback command (2.04.py):

def cut():
content_text.event_generate("<<Cut>>")

Then, define a callback command from the existing Cut menu, as follows:

edit_menu.add_command(label='Cut', accelerator='Ctrl+X', compound='left', image=cut_icon, command=cut)

Similarly, trigger the copy and paste functions from their respective menu items.

Next, we will move on to the implementation of the undo and redo features. The Tcl/Tk text documentation tells us that the Text widget has an unlimited Undo and Redo mechanism provided we set the undo option to true or 1. To leverage this option, let's first set the Text widget's undo option to true or 1, as shown in the following code:

content_text = Text(root, wrap='word', undo=1)

Now, if you open the text editor and try out the undo feature by using Ctrl + Z, it should work well. Now, we only have to associate the events to functions and call back the functions from the Undo menu. This is similar to what we did for cutcopy, and paste. Refer to the code in 2.03.py.

However, redo has a little quirk that needs to be addressed. By default, redo is not bound to the Ctrl + Y keys. Instead, Ctrl + Y is bound to the paste functionality. This is not how we expect the binding to behave, but it exists due to some historical reasons related to Tcl/Tk.

Fortunately, it is easy to override this functionality by adding an event binding, as follows:

content_text.bind('<Control-y>', redo) # handling Ctrl + small-case y
content_text.bind('<Control-Y>', redo) # handling Ctrl + upper-case y

Since an event binding like the one in the preceding code sends an event argument, the undo function must be able to handle this incoming parameter. Therefore, we'll add the event=None optional parameter to the redo function, as follows (2.04.py):

def redo(event=None):
content_text.event_generate("<<Redo>>")
return 'break'

Events propagate from the operating system level and are accessible to the window that subscribes to the event or wants to make use of it. The return 'break' expression in the preceding function tells the system that it has performed the event and that it should not be propagated further.

This prevents the same event from firing the paste event even though it is the default behavior in Tkinter. Now, Ctrl + Y fires the redo event instead of firing the paste event.

In fact, once we have performed an event, we do not want it to propagate further. Thus, we will add return break to all event-driven functions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.249.198