如何使用python类在kivy中使用下拉小部件
所以,我认为应该至少有两种方法可以让我在这个页面上有一个下拉菜单,但我不能同时工作.我是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,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 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' >第一个下拉菜单应附加到k??v文件底部已创建的按钮“使用说明”.它附加到python中的类,“CustomDropDown”,以及kv文件中的相应内容.你可能会注意到这个例子直接来自kivy文档.我想通过创建这条线: drop_down = CustomDropDown() 它给了我一个python和kivy方面的句柄来操纵它,但正如你可能会注意到当你运行它并单击“使用说明”时,没有任何反应. top_layout.add_widget(mainbutton) 被注释掉或应用程序甚至不会运行,引发错误: AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'add_widget' 我意识到我确实设定了 top_layout = ObjectProperty(None) 但这就是kivy建议为许多小部件做的事情,而且我已经和其他许多小部件做过了没有这个错误. 我确信这些问题中的一个或两个对于那里的人来说很简单.我错过了什么? 解决方法
对于这一部分,你有正确的基本想法,但犯了两个主要错误. 首先是你的类定义错误,你通常几乎不想在类级别放置代码,而应该在类方法中使用.如果要在实例化类时运行它,则应将其放在__init__方法中.我在下面粘贴的代码显示了执行此操作所需的简单更改.您还需要将drop_down更改为self.drop_down以设置类属性,而不仅仅是创建局部变量. 您有时希望在类变量中创建变量,这些变量可用于类的所有实例. Kivy属性就是这样的一个例子,它具有特殊的行为来控制它们在实际类实例中的行为方式.尽管如此,这是常规的一个例外,而不是您想要对大多数代码执行的操作. 实际上,我并不完全确定您的代码如何失败的细节(不确定执行顺序/时间),但最终代码无法正常运行且小部件未正确初始化.如果您遵循正常的__init__程序,这一切都很好. 第二个错误是你的kv文件有on_release:root.drop_down.open.问题是kv冒号右边的所有东西都是纯python,在这种情况下你不调用函数,你只需说明它的名字,所以没有任何反应.您需要使用root.drop_down.open(self)替换它以获得正确的行为,因为open方法需要一个小部件作为参数.
这是您的代码在类级别而不是在__init__方法中的错误方式的另一个症状.问题是top_layout是一个ObjectProperty,并且只在kv类中看起来像普通对象,因为Property在类实例中管理其接口的特殊方式.当你的代码在类级别时,它看不到那个特殊的接口,因为它并没有真正从类实例运行(同样的事情导致所有其他问题),所以它抛出一个错误,因为它看到了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','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,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',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)) #dropdown.bind(on_select=lambda instance,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,'y': .45} text_size: self.size valign: 'middle' halign: 'center' padding: 5 Button: id: translateButtonID text: 'Translate' pos_hint: {'x': .35,'y': .95} Button: #id: notesDropDownID id: btn_ddID text: 'Usage Notes' on_release: root.drop_down.open(self) Button: text: 'About' (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |