3

したがって、このページにドロップダウン メニューを表示するには、少なくとも 2 つの方法があるはずですが、どちらも機能しません。私は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()
    

    Python と kivy 側の両方でそれを操作するためのハンドルが与えられましたが、実行して [使用上の注意] をクリックしても何も起こらないことに気付くかもしれません。

  2. 2 番目のドロップダウン メニューは、kivy のドキュメントに従って Python で作成されます。アプリの上部に「使用上の注意 2」というタイトルの 3 つ目のボタンが作成されると思います。追加しようとするとエラーが発生します。今の行(私のファイルの53):

    top_layout.add_widget(mainbutton)
    

    コメントアウトされているか、アプリが実行されず、エラーが発生します:

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

    私が設定したことに気づきます

    top_layout = ObjectProperty(None)
    

    しかし、それはkivyが多くのウィジェットに対して行うことを提案していることであり、私はこのエラーなしで他の多くのウィジェットで行っています.

これらの問題のいずれかまたは両方は、そこにいる誰かにとっては簡単だと確信しています。私は何が欠けていますか?

4

2 に答える 2

5

.kv ファイルに配置できるドロップダウン ボタンが必要な他の kivy 初心者に役立つことを期待して、ここに投稿しています。

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))
于 2017-06-08T10:47:00.420 に答える
4

最初のドロップダウン メニューは、kv ファイルの下部にある、作成済みのボタン「使用上の注意」に添付する必要があります。pythonのクラス「CustomDropDown」に付属しており、kvファイルで対応しています。

この部分では、基本的な考え方は正しいのですが、主に 2 つの間違いを犯しています。

1 つ目は、クラスが間違って定義されていることです。通常、コードをクラス レベルに配置することはほとんどありません。代わりにクラス メソッドに配置する必要があります。クラスがインスタンス化されたときに実行する場合は、__init__メソッドに配置する必要があります。以下の貼り付けたコードは、これを行うために必要な簡単な変更を示しています。ローカル変数を作成するだけでなく、クラス属性を設定するには、に変更drop_downする必要もあります。self.drop_down

クラスのすべてのインスタンスで使用できるように、クラス変数で変数を作成したい場合があります。Kivy プロパティはこの例であり、実際のクラス インスタンスでの動作を制御する特別な動作を持っています。とはいえ、これは通常の例外であり、ほとんどのコードでやりたいことではありません。

実際、コードがどのように失敗するかの詳細については完全にはわかりませんが (実行順序/時間についてはわかりません)、最終的にはコードが適切に実行されず、ウィジェットが適切に初期化されません。__init__通常の手順に従えば、これで問題ありません。

2 番目の間違いは、kv ファイルにon_release: root.drop_down.open. 問題は、kv コロンの右側にあるすべてが純粋な python であることです。この場合、関数を呼び出さず、名前を指定するだけなので、何も起こりません。root.drop_down.open(self)open メソッドは引数としてウィジェットを必要とするため、正しい動作を得るにはこれを に置き換える必要があります。

2 番目のドロップダウン メニューは、kivy のドキュメントに従って Python で作成されます。アプリの上部に「使用上の注意 2」というタイトルの 3 つ目のボタンが作成されると思います。追加しようとするとエラーが発生します。今の行(私のファイルの53):

__init__これは、コードがメソッド内ではなく、クラス レベルで間違っていることのもう 1 つの症状です。問題は、top_layoutObjectProperty であり、Property がクラス インスタンスでそのインターフェイスを管理する特別な方法のために、kv クラスの通常のオブジェクトのようにしか見えないことです。コードがクラスレベルにある場合、実際にはクラスインスタンスから実行されていないため (他のすべての問題につながるのと同じこと)、その特別なインターフェイスは表示されません。その内容。

コードを以下のように変更すると__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'
于 2014-01-22T22:35:10.013 に答える