I'm working with the Text widget and I have an issue about old-school shortcuts that Tk uses.
Ie:
Select all: Ctrl + /
vs Ctrl + a
Cut: Ctrl + w
vs Ctrl + x
Copy: Meta + w
vs Ctrl + c
Paste: Ctrl + y
vs Ctrl + v
On Windows, all of them work except Ctrl+a.
1) Is it possible to redirect binds, so .bind('<Control-a>')
calls already bound Ctrl + /?
2) I tried for "select all":
txt_text.bind('<Control-a>', self.ctext_selectall)
Where:
def ctext_selectall(self, callback):
"""Select all text in the text widget"""
self.txt_text.tag_add('sel', '1.0', 'end')
But it does not work, since Ctrl+a works by default (cursor goes to the start). It function with some other, unbound, letter. Any chances of making this work if the solution under 1 is not possible?
The SelectableText widget shows a string of text with a solitary style. The string may break across various lines or may all be shown on a similar line contingent upon the design imperatives. To utilize SelectableText, there is just one required boundary which is the text to be shown was String.
See more widgets in the widget catalog. The text style to apply to descendant Text widgets without explicit style. The RichText widget displays text that uses multiple different styles. The text to display is described using a tree of TextSpan objects, each of which... A run of text with a single style. See more widgets in the widget catalog.
Python's design philosophy emphasizes code readability with its notable use of significant indentation") text.pack() #Create a button to select all the text in the text widget button= Button(win, text= "Select", background= "gray71", command=select_text) button.pack(pady=20, side= TOP) win.mainloop()
Tkinter text widgets are used for creating text fields that contain multiline user input. It has many inbuilt functions and methods which can be invoked to perform certain operations on text widgets.
The default bindings are applied to the widget class. When you do a bind, it affects a specific widget and that binding happens before the class binding. So what is happening is that your binding is happening and then the class binding is happening, which makes it seem as if your binding isn't working.
There are two ways to solve this. One, your ctext_selectall
can return the string "break" which will prevent the class binding from firing. That should be good enough to solve your immediate problem.
The second solution involves changing the class binding so that your preferred binding applies to all text widgets. You would do this using the bind_class
method.
Here's an example of rebinding the class:
def __init__(...):
self.root.bind_class("Text","<Control-a>", self.selectall)
def selectall(self, event):
event.widget.tag_add("sel","1.0","end")
effbot.org has a pretty decent writeup titled Events and Bindings. It goes into a little more detail about class and widget bindings and the order in which they occur.
Tk's binding mechanism is about the best of any GUI toolkit there is. Once you understand how it works (and it's remarkably simple) you'll find it's easy to augment or replace any or all of the default bindings.
Feel free to use the following code or at least check out how the select_all
methods are implemented in the DiacriticalEntry
and DiacriticalText
classes. If you choose to use the classes as they are in place of whatever widget you are currently using, you will also gain that advantange that users will be able to easily type in certain characters that would otherwise be more difficult to enter.
## {{{ http://code.activestate.com/recipes/576950/ (r3)
from tkinter import *
from tkinter.scrolledtext import ScrolledText
from unicodedata import lookup
import os
class Diacritical:
"""Mix-in class that adds keyboard bindings for accented characters, plus
other common functionality.
An inheriting class must define a select_all method that will respond
to Ctrl-A."""
accents = (('acute', "'"), ('grave', '`'), ('circumflex', '^'),
('tilde', '='), ('diaeresis', '"'), ('cedilla', ','),
('stroke', '/'), ('ring above', ';'))
def __init__(self):
# Fix some key bindings
self.bind("<Control-Key-a>", self.select_all)
# We will need Ctrl-/ for the "stroke", but it cannot be unbound, so
# let's prevent it from being passed to the standard handler
self.bind("<Control-Key-/>", lambda event: "break")
# Diacritical bindings
for a, k in self.accents:
# Little-known feature of Tk, it allows to bind an event to
# multiple keystrokes
self.bind("<Control-Key-%s><Key>" % k,
lambda event, a=a: self.insert_accented(event.char, a))
def insert_accented(self, c, accent):
if c.isalpha():
if c.isupper():
cap = 'capital'
else:
cap = 'small'
try:
c = lookup("latin %s letter %c with %s" % (cap, c, accent))
self.insert(INSERT, c)
# Prevent plain letter from being inserted too, tell Tk to
# stop handling this event
return "break"
except KeyError as e:
pass
class DiacriticalEntry(Entry, Diacritical):
"""Tkinter Entry widget with some extra key bindings for
entering typical Unicode characters - with umlauts, accents, etc."""
def __init__(self, master=None, **kwargs):
Entry.__init__(self, master, **kwargs)
Diacritical.__init__(self)
def select_all(self, event=None):
self.selection_range(0, END)
return "break"
class DiacriticalText(ScrolledText, Diacritical):
"""Tkinter ScrolledText widget with some extra key bindings for
entering typical Unicode characters - with umlauts, accents, etc."""
def __init__(self, master=None, **kwargs):
ScrolledText.__init__(self, master, **kwargs)
Diacritical.__init__(self)
def select_all(self, event=None):
self.tag_add(SEL, "1.0", "end-1c")
self.mark_set(INSERT, "1.0")
self.see(INSERT)
return "break"
def test():
frame = Frame()
frame.pack(fill=BOTH, expand=YES)
if os.name == "nt":
# Set default font for all widgets; use Windows typical default
frame.option_add("*font", "Tahoma 8")
# The editors
entry = DiacriticalEntry(frame)
entry.pack(fill=BOTH, expand=YES)
text = DiacriticalText(frame, width=76, height=25, wrap=WORD)
if os.name == "nt":
# But this looks better than the default set above
text.config(font="Arial 10")
text.pack(fill=BOTH, expand=YES)
text.focus()
frame.master.title("Diacritical Editor")
frame.mainloop()
if __name__ == "__main__":
test()
## end of http://code.activestate.com/recipes/576950/ }}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With