2014-01-22 3 views
3

Итак, я думаю, должно быть как минимум два способа, которыми я мог бы выпадающее меню на этой странице, но я не могу ни работать, ни работать. Я новичок в киви и программировании в целом, но я прочитал документацию, и кажется, что я просто не понимаю.Как использовать выпадающий виджет в kivy с классом python

Я создал следующий пример:

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) 
    

    но это то, что 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_down на self.drop_down, чтобы установить атрибут класса, а не просто сделать локальную переменную.

Иногда вы хотите создавать переменные в переменной класса, доступные для всех экземпляров класса. Примером этого являются свойства Kivy и имеют особое поведение, определяющее, как они ведут себя в реальных экземплярах класса. Тем не менее, это исключение из нормы, а не то, что вы хотите сделать с большей частью вашего кода.

На самом деле, я не совсем уверен в деталях того, как ваш код выходит из строя (не уверен в порядке выполнения/времени выполнения), но в конечном итоге код не запускается должным образом и виджеты не были правильно инициализированы.Это нормально, если вы следуете обычной процедуре __init__.

Вторая ошибка заключается в том, что ваш файл kv имеет on_release: root.drop_down.open. Проблема в том, что все, что находится справа от кик-кита, является чистым питоном, и в этом случае вы не вызываете функцию, вы просто указываете ее имя, и поэтому ничего не происходит. Вам нужно заменить это на 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 и появляется только как обычный объект в вашем классе 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', '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() 

киловольт:

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

 Смежные вопросы

  • Нет связанных вопросов^_^