重新绑定“全选”在文本小部件中

发布于 2024-11-04 23:14:42 字数 756 浏览 3 评论 0原文

我正在使用文本小部件,并且有一个关于 Tk 使用的老式快捷方式的问题。

即:

全选:Ctrl + /Ctrl + a
剪切:Ctrl + wCtrl + x
复制:Meta + wCtrl + c
粘贴:Ctrl + yCtrl + v

在 Windows 上,除了 Ctrl+a 之外,所有这些都有效。

1) 是否可以重定向绑定,以便 .bind('') 调用已经绑定的 Ctrl + /?

2)我尝试“全选”:

txt_text.bind('<Control-a>', self.ctext_selectall)

其中:

def ctext_selectall(self, callback):
    """Select all text in the text widget"""
    self.txt_text.tag_add('sel', '1.0', 'end')

但它不起作用,因为 Ctrl+a 默认情况下有效(光标转到开头)。它与其他一些未绑定的字母一起起作用。如果 1 下的解决方案不可行,是否有可能实现此目的?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

榆西 2024-11-11 23:14:42

默认绑定应用于小部件类。当您进行绑定时,它会影响特定的小部件,并且该绑定发生在类绑定之前。因此,发生的情况是您的绑定正在发生,然后类绑定正在发生,这使得您的绑定看起来好像不起作用。

有两种方法可以解决这个问题。第一,您的 ctext_selectall 可以返回字符串“break”,这将阻止类绑定触发。这应该足以解决您眼前的问题。

第二种解决方案涉及更改类绑定,以便您的首选绑定适用于所有文本小部件。您可以使用 bind_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 有一篇相当不错的文章,标题为 Events and Bindings 。它更详细地介绍了类和小部件绑定以及它们发生的顺序。

Tk 的绑定机制大约是所有 GUI 工具包中最好的。一旦您了解了它的工作原理(而且非常简单),您就会发现增强或替换任何或所有默认绑定都很容易。

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.

奈何桥上唱咆哮 2024-11-11 23:14:42

请随意使用以下代码,或者至少检查一下 select_all 方法是如何在 DiariticEntryDiariticText 类中实现的。如果您选择使用这些类来代替您当前使用的任何小部件,您还将获得这样的优势:用户将能够轻松地输入某些字符,否则这些字符将更难以输入。

## {{{ 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/ }}}

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/ }}}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文