【问题标题】:Re-binding "select all" in Text widget在文本小部件中重新绑定“全选”
【发布时间】:2011-08-17 18:04:29
【问题描述】:

我正在使用文本小部件,但我对 Tk 使用的老式快捷方式有疑问。

即:

全选:Ctrl + / vs Ctrl + a
剪辑:Ctrl + w vs Ctrl + x
复制:Meta + wCtrl + c
粘贴:Ctrl + y vs Ctrl + v

在 Windows 上,除了 Ctrl+a 之外,所有这些都可以工作。

1) 是否可以重定向绑定,所以 .bind('<Control-a>') 调用已经绑定 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 下的解决方案是不可能的,是否有可能完成这项工作?

【问题讨论】:

    标签: python tkinter widget tk


    【解决方案1】:

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

    有两种方法可以解决这个问题。一,您的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 工具包中最好的。一旦您了解了它的工作原理(并且非常简单),您会发现很容易增加或替换任何或所有默认绑定。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 如前所述,代码解决的问题不仅仅是选择所有文本;它还允许轻松输入带有变音符号的字符。这些类可以按原样使用来增强 Tkinter,或者 marw 可以只引用 select_all 方法来编写自己的。
      • 谢谢你,我想我有一天会回到这个 :)
      • 感谢"&lt;Control-Key-x&gt;&lt;Key&gt;" 引起我的注意。 :D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      相关资源
      最近更新 更多