2014-01-22 250 views
3

因此,我認爲至少應該有兩種方法,我可以在此頁面上有一個下拉菜單,但我可以不工作。我對kivy和編程一般都很陌生,但我已經閱讀過文檔,看起來我根本不明白。如何在python類中使用kivy中的下拉小部件

我已經創建了下面的例子:

import kivy 
kivy.require('1.7.2') # replace with your current kivy version ! 

from kivy.app import App 
from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.properties import ObjectProperty 
from kivy.uix.button import Button 
from kivy.uix.dropdown import DropDown 

class CustomDropDown(DropDown): 
    pass 

class HomeScreen(Screen): 
    translateInput = ObjectProperty(None) 
    translateButton = ObjectProperty(None) 
    translateLabel = ObjectProperty(None) 
    top_layout = ObjectProperty(None) 
    dd_btn = ObjectProperty(None) 
    drop_down = CustomDropDown() 
    #notes_dropdown = ObjectProperty(None) 


    dropdown = DropDown() 
    notes = ['Features', 'Suggestions', 'Abreviations', 'Miscellaneous'] 
    for note in notes: 
     # when adding widgets, we need to specify the height manually (disabling 
     # the size_hint_y) so the dropdown can calculate the area it needs. 
     btn = Button(text='%r' % note, size_hint_y=None, height=30) 

     # for each button, attach a callback that will call the select() method 
     # on the dropdown. We'll pass the text of the button as the data of the 
     # selection. 
     btn.bind(on_release=lambda btn: dropdown.select(btn.text)) 

     # then add the button inside the dropdown 
     dropdown.add_widget(btn) 

    # create a big main button 
    mainbutton = Button(text='Usage Notes 2', size_hint=(1, 1)) 

    # show the dropdown menu when the main button is released 
    # note: all the bind() calls pass the instance of the caller (here, the 
    # mainbutton instance) as the first argument of the callback (here, 
    # dropdown.open.). 
    mainbutton.bind(on_release=dropdown.open) 
    #dd_btn.bind(on_release=dropdown.open) 

    # one last thing, listen for the selection in the dropdown list and 
    # assign the data to the button text. 
    dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x)) 
    #dropdown.bind(on_select=lambda instance, x: setattr(dd_btn, 'text', x)) 

    #top_layout.add_widget(mainbutton) 


class dropdApp(App): 

    def build(self): 

     return HomeScreen() 



if __name__ == '__main__': 
    dropdApp().run() 

這是相應的.kv文件:

#:kivy 1.7.2 

<CustomDropDown>: 
    Button: 
     text: 'My first Item' 
     size_hint_y: None 
     height: 44 
     on_release: root.select('item1') 
    Label: 
     text: 'Unselectable item' 
     size_hint_y: None 
     height: 44 
    Button: 
     text: 'My second Item' 
     size_hint_y: None 
     height: 44 
     on_release: root.select('item2') 

<HomeScreen>: 
    id: home_screen 
    translateInput: translateInputID 
    translateButton: translateButtonID 
    translateLabel: labelID 
    top_layout: topLayoutID 
    #notes_dropdown: notesDropDownID 
    dd_btn: btn_ddID 

    orientation: 'vertical' 
    FloatLayout: 
     size_hint: 1, .95 
     TextInput: 
      id: translateInputID 
      text: 'cove' 
      #text: 'ﻰﺸَﻣ' 
      font_name: "data/fonts/DejaVuSans.ttf" 
      background_color: 1, 1, 1, 1 
      size_hint: .75, .1 
      multiline: False 
      pos_hint: {'x': .125, 'y': .45} 
      text_size: self.size 
      valign: 'middle' 
      halign: 'center' 
      padding: 5 

     Button: 
      id: translateButtonID 
      text: 'Translate' 
      pos_hint: {'x': .35, 'y': .35} 
      size_hint: .3, .08 
      valign: 'middle' 
      halign: 'center' 
      text_size: self.size 
      on_release: root.translateButtonPressed() 
      #on_press: root.manager.current = 'resultsscreen' 

     Label: 
      id: labelID 
      text: 'Translator' 
      text_size: self.size 
      valign: 'middle' 
      halign: 'center' 
      pos_hint: {'x': .3, 'y': .75} 
      size_hint: .4, .2 
      #font_name: "simpo.ttf" 
      #font_name: "5thgradecursive.ttf" 
      #font_name: "AGA-Rasheeq-Regular.ttf" 
      font_name: "data/fonts/DejaVuSans.ttf" 
      font_size: 50 

    BoxLayout: 
     id: topLayoutID 
     #cols: 2 
     size_hint: 1, .05 
     pos_hint: {'x': 0, 'y': .95} 
     Button: 
      #id: notesDropDownID 
      id: btn_ddID 
      text: 'Usage Notes' 
      on_release: root.drop_down.open 
     Button: 
      text: 'About' 
  1. 的第一個下拉菜單中應附已創建按鈕,「使用說明」,位於kv文件的底部。它被附加到Python中的類CustomDropDown和kv文件中的相應文件中。您可能會注意到這個例子是直接從kivy文檔中找出來的。我想通過創建行:

    drop_down = CustomDropDown() 
    

    它給了我一個手柄都蟒蛇和kivy側操縱它,但是,當您運行它,你可能會注意到,點擊「使用說明」,沒有任何反應。

  2. 第二個下拉菜單在python中也是在kivy文檔之後創建的。我認爲它會在應用程序頂部創建第三個按鈕,標題爲「使用說明2」。我嘗試添加它時出現錯誤。現在(我的文件53)行:

    top_layout.add_widget(mainbutton) 
    

    被註釋掉或應用程序將不能運行,提高了錯誤:

    AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'add_widget' 
    

    這我知道,我沒有設置

    top_layout = ObjectProperty(None) 
    

    但這就是基維建議爲許多小部件所做的事情,並且我已經與其他許多人一起完成了這個錯誤。

我確信這些問題中的一個或兩個對於那裏的人來說很簡單。我錯過了什麼?

回答

4

The first drop-down menu should be attached to the already created button, "Usage Notes", at the bottom of the kv file. It is attached to the class in python, "CustomDropDown", and the corresponding in the kv file.

對於這部分,你有正確的基本思想,但犯了兩個主要錯誤。

第一個是你的類定義錯了,你通常幾乎從不想把代碼放在類級別,它應該在類方法中代替。如果你希望它在類被實例化時運行,你應該把它放在__init__方法中。下面我粘貼的代碼顯示了執行此操作所需的簡單更改。您還需要將drop_down更改爲self.drop_down以設置類屬性,而不是僅創建局部變量。

有時您希望在類變量中創建可用於類的所有實例的變量。 Kivy屬性就是這樣一個例子,並且具有特殊的行爲來控制它們在實際的類實例中的行爲。儘管如此,這是規範的一個例外,而不是你想要用你的大部分代碼做的事情。

實際上,我並不完全確定代碼失敗的細節(不確定執行順序/時間),但最終代碼無法正常運行,並且小部件未正確初始化。如果您遵循正常的__init__程序,這一切都很好。

第二個錯誤是您的kv文件有on_release: root.drop_down.open。問題在於,一個kv冒號右邊的所有內容都是純python,在這種情況下,您不會調用該函數,您只需聲明它的名稱,因此什麼都不會發生。您需要用root.drop_down.open(self)替換它以獲得正確的行爲,因爲open方法需要一個小部件作爲參數。

The second drop-down menu is created in python also following the kivy documentation. I would think it would create a third button at the top of the app, titled, "Usage Notes 2". I just get an error when I try to add it. Right now the line (53 on my file):

這是你的代碼是不正確的一流水平,而不是在__init__方法的方式另一種症狀。問題在於top_layout 的一個ObjectProperty,並且由於Property在類實例中管理其接口的特殊方式,因此只會顯示爲您的kv類中的普通對象。當你的代碼處於類級別時,它不會看到那個特殊的接口,因爲它不是真正從類實例運行(導致所有其他問題的同一件事),所以它會拋出一個錯誤,因爲它看到的是ObjectProperty而不是其內容。

隨着代碼改變如下,添加小部件工作正常,因爲__init__運行從類實例,並可以像屬性正常交互屬性。

我做了如下的變化,以及下拉菜單似乎都正常工作:

import kivy 
kivy.require('1.7.2') # replace with your current kivy version ! 

from kivy.app import App 
from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.properties import ObjectProperty 
from kivy.uix.button import Button 
from kivy.uix.dropdown import DropDown 

class CustomDropDown(DropDown): 
    for i in range(5): 
     print i 


class HomeScreen(Screen): 
    translateInput = ObjectProperty(None) 
    translateButton = ObjectProperty(None) 
    translateLabel = ObjectProperty(None) 
    top_layout = ObjectProperty(None) 
    dd_btn = ObjectProperty(None) 

    def __init__(self, *args, **kwargs): 
     super(HomeScreen, self).__init__(*args, **kwargs) 
     self.drop_down = CustomDropDown() 
     #notes_dropdown = ObjectProperty(None) 


     dropdown = DropDown() 
     notes = ['Features', 'Suggestions', 'Abreviations', 'Miscellaneous'] 
     for note in notes: 
      # when adding widgets, we need to specify the height manually (disabling 
      # the size_hint_y) so the dropdown can calculate the area it needs. 
      btn = Button(text='%r' % note, size_hint_y=None, height=30) 

      # for each button, attach a callback that will call the select() method 
      # on the dropdown. We'll pass the text of the button as the data of the 
      # selection. 
      btn.bind(on_release=lambda btn: dropdown.select(btn.text)) 

      # then add the button inside the dropdown 
      dropdown.add_widget(btn) 

     # create a big main button 
     mainbutton = Button(text='Usage Notes 2', size_hint=(1, 1)) 
     print 'yay' 

     # show the dropdown menu when the main button is released 
     # note: all the bind() calls pass the instance of the caller (here, the 
     # mainbutton instance) as the first argument of the callback (here, 
     # dropdown.open.). 
     mainbutton.bind(on_release=dropdown.open) 
     #dd_btn.bind(on_release=dropdown.open) 

     # one last thing, listen for the selection in the dropdown list and 
     # assign the data to the button text. 
     dropdown.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x)) 
     #dropdown.bind(on_select=lambda instance, x: setattr(dd_btn, 'text', x)) 

     self.top_layout.add_widget(mainbutton) 

class dropdApp(App): 

    def build(self): 

     return HomeScreen() 



if __name__ == '__main__': 
    dropdApp().run() 

KV:

<CustomDropDown>: 
    Button: 
     text: 'My first Item' 
     size_hint_y: None 
     height: 44 
     on_release: root.select('item1') 
    Label: 
     text: 'Unselectable item' 
     size_hint_y: None 
     height: 44 
    Button: 
     text: 'My second Item' 
     size_hint_y: None 
     height: 44 
     on_release: root.select('item2') 

<HomeScreen>: 
    id: home_screen 
    translateInput: translateInputID 
    translateButton: translateButtonID 
    translateLabel: labelID 
    top_layout: topLayoutID 
    #notes_dropdown: notesDropDownID 
    dd_btn: btn_ddID 

    orientation: 'vertical' 
    FloatLayout: 
     size_hint: 1, .95 
     TextInput: 
      id: translateInputID 
      text: 'cove' 
      #text: 'ﻰﺸَﻣ' 
      font_name: "data/fonts/DejaVuSans.ttf" 
      background_color: 1, 1, 1, 1 
      size_hint: .75, .1 
      multiline: False 
      pos_hint: {'x': .125, 'y': .45} 
      text_size: self.size 
      valign: 'middle' 
      halign: 'center' 
      padding: 5 

     Button: 
      id: translateButtonID 
      text: 'Translate' 
      pos_hint: {'x': .35, 'y': .35} 
      size_hint: .3, .08 
      valign: 'middle' 
      halign: 'center' 
      text_size: self.size 
      on_release: root.translateButtonPressed() 
      #on_press: root.manager.current = 'resultsscreen' 

     Label: 
      id: labelID 
      text: 'Translator' 
      text_size: self.size 
      valign: 'middle' 
      halign: 'center' 
      pos_hint: {'x': .3, 'y': .75} 
      size_hint: .4, .2 
      #font_name: "simpo.ttf" 
      #font_name: "5thgradecursive.ttf" 
      #font_name: "AGA-Rasheeq-Regular.ttf" 
      font_name: "data/fonts/DejaVuSans.ttf" 
      font_size: 50 

    BoxLayout: 
     id: topLayoutID 
     #cols: 2 
     size_hint: 1, .05 
     pos_hint: {'x': 0, 'y': .95} 
     Button: 
      #id: notesDropDownID 
      id: btn_ddID 
      text: 'Usage Notes' 
      on_release: root.drop_down.open(self) 
     Button: 
      text: 'About' 
3

我希望在這裏張貼這一點,它可以幫助其他kivy初學者誰只需要一個下拉按鈕,他們可以放在.kv文件中。

class DropBut(Button): 
    def __init__(self, **kwargs): 
    super(DropBut, self).__init__(**kwargs) 
    self.drop_list = None 
    self.drop_list = DropDown() 

    types = ['Item1', 'Item2', 'Item3', 'Item4', 'Item5', 'Item6'] 

    for i in types: 
     btn = Button(text=i, size_hint_y=None, height=50) 
     btn.bind(on_release=lambda btn: self.drop_list.select(btn.text)) 

     self.drop_list.add_widget(btn) 

    self.bind(on_release=self.drop_list.open) 
    self.drop_list.bind(on_select=lambda instance, x: setattr(self, 'text', x)) 
相關問題