Tkinter question: cut, copy and paste?

Russell E. Owen owen at astroNOJNK.washington.edu.invalid
Fri Aug 11 19:10:33 EDT 2000


In article <8mvdj1$ekg$1 at nnrp1.deja.com>, John Grayson 
<johngrayson at home.com> wrote:

>> So...how do you enable Cut, Copy and Paste in Tkinter?
>
>I played around for a few minutes:
>
>See if this example gives you some clues. Note that you *can* call
>Tk routines from Tkinter...

That was very helpful. I'd not known how to call tk directly. Further 
tests turned up the following:
- the default Edit menu sends the virtual events <<Cut>>, <<Copy>> and 
<<Paste>>, but nobody seems to be listening to them.

- I have no idea how to access the default menus to modify them. (I'd 
like to add a "Select All" item to the Edit menu, for example):
root = Tk()
root["menu"]
returns nothing.

- Hence I've been creating my own menu bar and ditching the virtual 
events, for now.

- Text widgets respond to tk_textCut, etc. Entry widgets do not (except 
tk_textPaste, for some reason). Hence Entry widgets need special code.

- MacPython 1.5.2's included Tkinter does not seem to accept 
tk_textSelectTo and so on, so I've not found a way to implement Select 
All on a Text widget.

In summary, Tk's handling of cut, copy and paste is surprisingly 
inadequate. I've appended some minimal code that shows all this. (Uses 
Mac standards for the menu names and accelerators; obviously tuning it 
for each platform would require additional fussing).  Maybe over time I 
can beef it up enough to do everything, but it seems strange that so 
much effort is required for such basic operations. I'm starting to 
wonder how anybody manages to build Tk applications that have reasonable 
feel. I guess it's time to have a look at wx.

-- Russell

import sys
from Tkinter import *

class MinimalMenus (Tk):
    def __init__(self, **kargs):
        """Creates a new application with minimal Mac-standard menus
        Returns the root window, just like Tk()
        To use:
            root = MinimalMenus()
            # configure root and/or create other windows, etc...
            root.mainloop()
        """
        Tk.__init__(self)
        # apply(Tk.__init__, (self,), kargs)

        # create standard menu bar
        menu = Menu(self)
        self.config(menu=menu)

        # add file menu
        filemenu = Menu(menu)
        menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(
            label="Close",
            command=self.doClose,
            accelerator="Command-W")
        filemenu.add_command(
            label="Quit",
            command=self.doQuit,
            accelerator="Command-Q")

        # add edit menu
        editmenu = Menu(menu)
        menu.add_cascade(label="Edit", menu=editmenu)
        editmenu.add_command(
            label="Cut",
            command=self.doCut,
            accelerator="Command-X")
        editmenu.add_command(
            label="Copy",
            command=self.doCopy,
            accelerator="Command-C")
        editmenu.add_command(
            label="Paste",
            command=self.doPaste,
            accelerator="Command-V")
        editmenu.add_command(
            label="Select All",
            command=self.doSelectAll,
            accelerator="Command-A")

    def doClose(self, evt=None):
        win = self.focus_get().winfo_toplevel()
        win.destroy()

    def doQuit(self, evt=None):
        sys.exit()

    def doCut (self, evt=None):
        widget = self.focus_get()
        if isinstance(widget, Entry):
            if widget.selection_present():
                widget.clipboard_clear()
                widget.clipboard_append(widget.selection_get())
                widget.delete(SEL_FIRST, SEL_LAST)
        else:
            # works for Text, not for Entry (why?); fails quietly
            widget.tk.call('tk_textCut', widget._w)

    def doCopy (self, evt=None):
        widget = self.focus_get()
        if isinstance(widget, Entry):
            if widget.selection_present():
                widget.clipboard_clear()
                widget.clipboard_append(widget.selection_get())
        else:
            # works for Text, not for Entry (why?); fails quietly
            widget.tk.call('tk_textCopy', widget._w)

    def doPaste (self, evt=None):
        widget = self.focus_get()
        # works for Text and Entry, at least; fails quietly
        widget.tk.call('tk_textPaste', widget._w)

    def doSelectAll(self, evt=None):
        widget = self.focus_get()
        if isinstance(widget, Text):
            # the following commented-out code fails on MacPython
            # because the tk commands themselves aren't recognized;
            # hence I am not sure if the code is correct
            print """Cannot yet "Select All" in Text widgets"""
    #       widget.tk_textResetAnchor("1.0")
    #       widget.tk_textSelectTo(END)
        elif isinstance(widget, Entry):
            widget.selection_range(0, END)
            widget.icursor(0)

if __name__ == "__main__":
    root = MinimalMenus()
    aText = Text(root, width=30, height=2)
    aText.insert(END, "some text to manipulate")
    aText.grid(row=0, column=0, sticky=NSEW)
    anEntry = Entry(root)
    anEntry.insert(0, "more text")
    anEntry.grid(row=1, column=0, sticky=EW)
    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.mainloop()



More information about the Python-list mailing list