2016-04-26 145 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事件來觸發該功能。