2014-01-22 8 views
3

그래서이 페이지에서 드롭 다운 메뉴를 가질 수있는 방법은 최소한 두 가지가 있어야한다고 생각합니다. 그러나 둘 다 작동하지 않을 수 있습니다. 나는 kivy와 프로그래밍에 익숙하지 않지만 일반적으로 문서를 읽었으며 이해가 안되는 것 같습니다.kivy에서 python 클래스로 드롭 다운 위젯을 사용하는 방법

I는 다음과 같은 예를 만들었다 :

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 파일 맨 아래의 "사용법 메모"버튼을 클릭하십시오. 그것은 파이썬의 클래스 인 "CustomDropDown"과 kv 파일에 상응합니다. 이 예제는 kivy 문서에서 곧바로 볼 수 있습니다.

    drop_down = CustomDropDown() 
    

    그것은 파이썬하고 조작 할 수있는 kivy 측면 모두에서 나에게 핸들을 준,하지만 당신은 당신이 그것을 실행할 때 통지 및 "사용주의"를 클릭 하듯 아무 일도 발생하지 않습니다 : I 라인을 만들어 생각했다.

  2. 번째 메뉴도 kivy 문서 다음 파이썬 생성된다. 나는 그것이 응용 프로그램의 상단에 "사용법 메모 2"라는 세 번째 버튼을 만들 것이라고 생각합니다. 추가하려고하면 오류가 발생합니다. (내 파일에 대한 53) 현재 라인 : 오류 제기

    top_layout.add_widget(mainbutton) 
    

    은 주석 또는 응용 프로그램도 실행되지 않을 것입니다 : 내가 설정 않았다는 것을 깨닫게 어느

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

    top_layout = ObjectProperty(None) 
    

    는하지만 kivy 많은 위젯 일을 제안 무엇이며,이 오류없이 많은 다른 사람들과 함께 일했다.

나는이 문제 중 하나 또는 둘 모두가 누군가에게 간단하다고 확신합니다. 내가 뭘 놓치고 있니?

답변

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_downself.drop_down으로 변경해야합니다.

때때로 클래스 변수에 변수를 만들고 싶습니다.이 변수는 클래스의 모든 인스턴스에서 사용할 수 있습니다. Kivy 속성은 이에 대한 예이며 실제 클래스 인스턴스에서 어떻게 작동 하는지를 관리하는 특수 동작을가집니다. 그럼에도 불구하고 이것은 표준에 대한 예외이며 대부분의 코드로 수행하려는 것이 아닙니다.

사실, 코드가 어떻게 실패하는지 (실행 순서/시간은 확실하지 않음)에 대해서는 확신 할 수 없지만 궁극적으로 코드가 제대로 실행되지 않고 위젯이 제대로 초기화되지 않습니다.정상적인 __init__ 절차를 따르는 것이 좋습니다.

두 번째 실수는 kv 파일에 on_release: root.drop_down.open이 있다는 것입니다. 문제는 kv 콜론의 오른쪽에있는 모든 것이 순수한 파이썬이며,이 경우 함수를 호출하지 않는다는 것입니다. 이름 만 언급하면 ​​아무 일도 일어나지 않습니다. open 메소드가 위젯을 인수로 필요로하므로 올바른 동작을 얻으려면 이것을 root.drop_down.open(self)으로 대체해야합니다.

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))