[Tkinter-discuss] (no subject)
Michael Lange
klappnase at web.de
Mon Dec 20 18:12:09 CET 2010
Hi
Thus spoketh Vasilis Vlachoudis <Vasilis.Vlachoudis at cern.ch>
unto us on Mon, 20 Dec 2010 14:05:33 +0000:
> Dear all,
>
> the default behavior of the Entry/Text on how they react to Cut&Paste
> is a bit problematic (at least on linux) Imaging that the entry
> contains the text "foobar" with the first 3 letters "foo" highlighted
> and we have the word "test" copied previously on the clipboard. When we
> press Ctrl-V to paste the clipboard text "test", tk will not delete the
> "foo" before inserting the "test" and we will get the text "footestbar"
> with the "foo" still highlighted. (The "test" will be inserted at the
> location of the cursor)
>
> Normally what the user will expect will be to delete first the "foo"
> and then insert the "test" getting the string "testbar" with the "test"
> highlighted.
>
> Do you know how I can change the behavior without the need to override
> the default Entry class and substitute it in the whole project?
This behavior is intentional by Tk developers, maybe it matched some old
Motif standard, I don't know for sure. The binding is defined in
entry.tcl as binding to the virtual <<Paste>> event:
##################################
bind Entry <<Paste>> {
global tcl_platform
catch {
if {[tk windowingsystem] ne "x11"} {
catch {
%W delete sel.first sel.last
}
}
%W insert insert [::tk::GetSelection %W CLIPBOARD]
tk::EntrySeeInsert %W
}
}
#################################
You see, in the fourth line they omit the deleting of the selection
on X11 systems.
If you want to change this, you must define a new callback for <<Paste>>
events for the Entry class and use bind_class() to override the default
binding. We can use most of the code from the default binding and "translate"
it into python, where %W corresponds with the event's widget attribute,
and the catch command works much like a try..except in python; the
"special" tk commands need to be wrapped in the widget's tk.call()
function:
######################################
from Tkinter import *
root = Tk()
def entry_paste(event):
try:
event.widget.delete('sel.first', 'sel.last')
except TclError:
pass# nothing is selected
# in tk.call() use the widget's string representation event.widget._w
# instead of event.widget, which is the widget instance itself
text = event.widget.tk.call('::tk::GetSelection', event.widget._w, 'CLIPBOARD')
event.widget.insert('insert', text)
event.widget.tk.call('tk::EntrySeeInsert', event.widget._w)
root.bind_class('Entry', '<<Paste>>', entry_paste)
# create an Entry to see if it works:
Entry(root).pack()
root.mainloop()
######################################
I hope this helps
Michael
.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.
Vulcans do not approve of violence.
-- Spock, "Journey to Babel", stardate 3842.4
More information about the Tkinter-discuss
mailing list