Kivy的TextInput小部件中Tab/Enter(和其他按键)的处理方式

17

我正在使用Kivy框架编写应用程序,但遇到了一个小而烦人的问题:我不知道如何处理文本字段中的 Tab/Enter/Arrow 键,以便按下其中任意一个键都能触发事件,例如切换焦点 (跳转) 到另一个 TextInput 或启动类似于 send_form() 的操作。

请问有人可以解决这个问题吗?


2
我认为目前Kivy对这种功能的支持不是很多,它们似乎主要关注于触摸。你可以提交一个功能请求,或考虑修改Kivy的TextInput类;从这里开始,看看第1266行(elif key == 9: # tab)。也许在那里触发自己的自定义事件? - Daniel Kinsman
4个回答

49

Kivy 1.9提供在文本输入框中设置write_tab: False的能力(请查看文档),从而使Tab键聚焦到下一个可聚焦控件。

Kivy允许通过设置multiline: Falseon_text_validate: root.foo()来调度事件,以使Enter键能够发出事件。

因此,要创建具有所需Enter和Tab功能的文本输入控件,请按照以下步骤进行:

TextInput:
    write_tab: False
    multiline: False
    on_text_validate: root.foo()

1
谢谢,尽管对于安卓(如 Kivy==1.10.0)无效。 - Andre Miras
这非常有帮助!谢谢你!对于其他人想知道kivymd的文本输入是否继承自kivy TextInput的问题,答案是肯定的。 - tahesse
谢谢,它是否也可以启用“shift+tab”以相反的方向移动,即移动到上一个可聚焦小部件?我尝试过了,但只能在正向移动时工作。 - Neeraj

9

我刚发现这个旧问题,觉得我可以贡献一份力量。我也需要制表符/回车键跳到下一个字段。我按照 @tshirtman 的建议做了。这是我的自定义TextInput类:

from kivy.uix.textinput import TextInput


class TabTextInput(TextInput):

    def __init__(self, *args, **kwargs):
        self.next = kwargs.pop('next', None)
        super(TabTextInput, self).__init__(*args, **kwargs)

    def set_next(self, next):
        self.next = next

    def _keyboard_on_key_down(self, window, keycode, text, modifiers):
        key, key_str = keycode
        if key in (9, 13) and self.next is not None:
            self.next.focus = True
            self.next.select_all()
        else:
            super(TabTextInput, self)._keyboard_on_key_down(window, keycode, text, modifiers)

这使你能够在实例化输入时传递next,或者在现有输入上调用set_next。9和13是制表符和回车键的关键代码。对我来说效果很好。

哦,_keyboard_on_key_down方法,正是我需要的!谢谢! - swietyy
所以我有一个TextInput实例,带有一个调用:on_text_validate: root.change_context()。我该如何将此更改(在我的kv文件中)为TabTextInput,以便我的TextInput字段以多行模式运行? - Bill Bridge

5

正如Daniel Kinsman在他的评论中建议的那样,您可以对TextInput进行子类化,为选项卡支持添加“previous”和“next”ObjectProperties(使用对其他小部件的引用在kv中很容易设置),并以不同的方式处理键盘事件。目前没有现成的支持,但如果您想要开发这样的修改,请向我们提出功能请求或在freenode上的#kivy中讨论。

https://github.com/kivy/kivy/blob/master/kivy/uix/textinput.py#L1188

也许在小部件上添加这样的支持并添加一些焦点逻辑会更好,这样tab/enter将对任何可激活的小部件产生影响,而像滑块之类的小部件也使用右/左/上/下键。
因此,在Kivy方面还有很多工作要做,如果您有兴趣帮助,您可以真正加快它的实现速度,我们会帮助您 :)

我确实需要键盘支持,即在按下“F1”或“<spacebar>”或“Ctrl+T”时激活(单击)小部件,在Spinner上的选项之间使用箭头移动等。这将提高“普通”PC的可用性。我会尽力帮忙 :) - minder
3
类似于这个主题,Kivy文档中的on_text_validate事件只在multiline=False模式下触发,当用户按下“回车”键时会取消文本输入框的焦点。如何在按下回车键后保持焦点? - securecurve

0

[点数不足以仅评论,所以在这里添加...]

需要注意的是,键盘的下一个行为只有在下一个字段由相同的键盘布局管理时才能轻松工作。然而,高级应用程序将具有:

  • 用户名(qwerty)
  • 密码(password)
  • ID(数字) 等等

因此,上述方法确实行不通。

在kv文件中:

    MyTextInput:
        next: idTheNextFieldBelowThis

在你的MyTextInput类中:
    def insert_text(self, value, from_undo=False):
        #
        # Unfortunately the TextInput write_tab behavior only works if the next field is the same exact keyboard
        # type.
        #
        if not value[-1:] == '  ':
            return super(MyTextInput, self).insert_text(value, from_undo=from_undo)
        r = super(MyTextInput, self).insert_text(value[:-1], from_undo=from_undo)
        if self.next is not None:
            self.next.focus = True
        return r

这个问题现在已经7年了,它还适用吗? - minder
1
是的,绝对没问题。 - OutsourcedGuru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接