2016-04-26 142 views
2

我正在使用kivy创建应用程序。所以我不认为我正确理解FloatInput的on_focus行为。Kivy - TextInput on_focus行为问题

让我先描述一下我在这里要做的。我试图在用户点击一个TextInput时激活一个弹出小键盘(这个小键盘只有数字0-9的按钮和一个“回车”按钮)。接下来,一旦用户在弹出的数字小键盘中提供了一个数字并点击“输入”按钮,弹出窗口应该关闭,并且TextInput的文本字段应该更新为用户输入的数字。

但是,我遇到了一个问题。基本上,我有一个如上所述构建多个TextInputs的表单(以后我将它们称为“FloatInputs”b/c,这就是我所命名的)。我第一次将值输入到其中一个FloatInput中时,一切都按预期工作。但是,只要我尝试在第二个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代码:

<[email protected]>: 
    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' 
+0

第一句应该以TextInput而不是FloatInput结尾。我对这种混乱表示抱歉。 – MV22

回答

1

好了玩这个后多一点,我发现一个解决方案来实现的功能,我想了。然而,要清楚这确实解决了为什么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)”的碰撞可以防止相同类型的所有窗口小部件响应用户的触摸错误。

我希望这可以帮助别人!

+0

在最近的构建中,使用两个参数调用on_touch_down方法。第一个位置参数(除自身以外)是发生触摸的对象的实例。第二个参数是触摸事件对象。 –

+0

如果您使用触摸事件,那么您应该返回True以停止我猜测的传播。 –

+0

您能否提供完整的工作代码,以便我可以看到您描述的功能?我有类似的问题,并希望看到它可能与我的应用程序集成。谢谢。 – Griff

0

在点击文本输入后尝试调用模态时,我遇到了类似的问题。如果我尝试使用on_focus,它会启动两次。对我有用的是设置is_focusable = False并使用on_touch_down事件来触发该功能。