[英]Kivy - TextInput on_focus behavior issue
我正在使用 kivy 创建一个应用程序。 所以我认为我没有正确理解 FloatInput 的 on_focus 行为。
让我先描述一下我在这里要做的事情。 当用户单击 TextInput 时,我试图激活一个弹出式小键盘(这个小键盘只有数字 0-9 的按钮和一个“输入”按钮)。 接下来,一旦用户在弹出式小键盘中提供了一个数字并点击了“输入”按钮,弹出窗口应该关闭并且 TextInput 的文本字段应该更新为用户输入的数字。
但是,我遇到了一个问题。 本质上,我有一个如上所述构造的具有多个 TextInput 的表单(我将在下文中将它们称为“FloatInputs”b/c,这就是我给它们命名的原因)。 我第一次在其中一个 FloatInputs 中输入值时,一切都按预期工作。 但是每当我尝试在第二个 FloatInput 中输入一个数字时就会出现问题。 具体来说, on_focus 函数以某种方式被调用两次,因此用户必须两次将该值输入到弹出窗口中(这显然不理想,因为它会使用户感到沮丧)。
如果这是一个愚蠢的问题,我深表歉意,但我一直对此感到困惑。 我认为问题的核心在于 TextInput 和弹出窗口小部件的聚焦顺序,但我在这里可能是错的。 如果有人可以提供有关如何修复此错误的建议,我将不胜感激。
这是相关的python代码:
class FloatInput(TextInput):
def on_focus(self, instance, value):
print 'ON FOCUS CALLED - THIS SHOULD ONLY BE CALLED ONCE!'
# Adding this helped part of the problem (however, on_focus is still being called twice???)
self.unfocus_on_touch = False
prompt_content = BoxLayout(orientation='vertical') # Main layout
num_pad = NumPadWidget()
prompt_content.add_widget(num_pad)
def my_callback(instance):
self.text = num_pad.ids.num_label.text
self.popup.dismiss()
# Now define the popup, with the content being the layout:
self.popup = Popup(id='num_pad_popup', title='Enter value', content=prompt_content, size_hint=(0.8,0.5), autodismiss=False)
num_pad.ids.enter_btn.bind(on_press=my_callback)
# Open the pop-up:
self.popup.open()
这是相关的 kv 代码:
<NumPadButton@Button>:
font_size: '16dp'
bold: True
<NumPadWidget>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 1
id: num_label
Label:
id: num_label
text: ''
BoxLayout:
size_hint_y: 5
orientation: 'vertical'
BoxLayout:
NumPadButton:
text: '7'
on_press:
num_label.text = num_label.text + '7'
NumPadButton:
text: '8'
on_press:
num_label.text = num_label.text + '8'
NumPadButton:
text: '9'
on_press:
num_label.text = num_label.text + '9'
BoxLayout:
NumPadButton:
text: '4'
on_press:
num_label.text = num_label.text + '4'
NumPadButton:
text: '5'
on_press:
num_label.text = num_label.text + '5'
NumPadButton:
text: '6'
on_press:
num_label.text = num_label.text + '6'
BoxLayout:
NumPadButton:
text: '1'
on_press:
num_label.text = num_label.text + '1'
NumPadButton:
text: '2'
on_press:
num_label.text = num_label.text + '2'
NumPadButton:
text: '3'
on_press:
num_label.text = num_label.text + '3'
BoxLayout:
NumPadButton:
text: '0'
on_press:
num_label.text = num_label.text + '0'
NumPadButton:
text: '.'
on_press:
num_label.text = num_label.text + '.'
NumPadButton:
text: 'del'
on_press:
num_label.text = num_label.text[:-1]
BoxLayout:
BoxLayout:
size_hint_x: 1
NumPadButton:
text: 'C'
on_press:
num_label.text = ''
BoxLayout:
size_hint_x: 2
NumPadButton:
id: enter_btn
text: 'Enter'
好吧,在玩了更多之后,我找到了一个解决方案来实现我想要的功能。 但是,要清楚这确实解决了为什么 on_focus 行为以我在原始帖子中描述的方式行事。
如果有人感兴趣,这里有一个解决方法:
class FloatInput(TextInput):
def __init__(self, **kwargs):
super(FloatInput, self).__init__(**kwargs)
def on_touch_down(self, touch):
if self.collide_point(touch.x, touch.y):
prompt_content = BoxLayout(orientation='vertical') # Main layout
num_pad = NumPadWidget()
prompt_content.add_widget(num_pad)
def my_callback(instance):
self.text = num_pad.ids.num_label.text
self.popup.dismiss()
# Now define the popup, with the content being the layout:
self.popup = Popup(id='num_pad_popup', title='Enter value', content=prompt_content, size_hint=(0.8,0.5), autodismiss=False)
num_pad.ids.enter_btn.bind(on_press=my_callback)
# Open the pop-up:
self.popup.open()
具体来说,此解决方案通过使用 on_touch_down 而不是查找 TextInput 的焦点来工作。 此外,寻找与“if self.collide_point(touch.x, touch.y)”的碰撞可以防止所有相同类型的小部件响应用户触摸的错误。
我希望这对某人有所帮助!
值得一提的是,TextInput 的 on_focus() 方法如下所示:
def on_focus(self, instance, value, *largs):
如果值为True ,则为焦点事件。 如果它是False ,那么它是一个散焦/模糊事件。 我真的不知道为什么他们对两个事件都使用一个处理程序,但他们以这种方式实现了它。 我认为其他任何人都会将其实现为 on_focus()/on_blur()。
这可能是一个方法可能会触发两次的原因。
在单击文本输入后尝试调用模态时,我遇到了类似的问题。 如果我尝试使用on_focus
它会触发两次。 对我is_focusable = False
是设置is_focusable = False
并使用on_touch_down
事件来触发该函数。
确保您的所有 TextInputs(在您的情况下为“FloatInput”)在您的代码中尽快将小部件属性unfocus_on_touch设置为False 。 这意味着在 kv 文件、工厂构建器字符串(如下)或一些包装的__init__
类函数中。 在on_focus事件中设置此属性为时已晚,可能会导致它被触发两次。
Builder.load_string('''
<RootWidget>:
TextInput:
unfocus_on_touch: False
id: id_textbox
text: 'hello world'
multiline: False
font_size: 20
''')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.