使用MDDropdownMenu

时间:2019-08-12 18:42:40

标签: python android python-3.x kivy kivy-language

单击MDDropdownMenu中列表中的标签时,我无法给出按钮的文本。在我的测试main.py和main.kv中,它一直在工作,但是当它在主代码中实现时-出现错误AttributeError: 'super' object has no attribute '__getattr__'

有我的main.py:

 # encoding=utf8 
import sys
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.core.text import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.screenmanager import SlideTransition
from kivy.properties import ObjectProperty, NumericProperty, StringProperty, BooleanProperty, ListProperty
from kivy.utils import get_hex_from_color
from kivy.metrics import dp, sp, pt
from kivy.clock import Clock
from kivy.uix.textinput import TextInput

from kivymd.theming import ThemeManager
from kivymd.dialog import MDDialog
from kivymd.label import MDLabel
from kivymd.button import MDRoundFlatButton
from kivymd.button import MDRaisedButton
from kivymd.list import ILeftBodyTouch
from kivymd.popupscreen import MDPopupScreen
from newpickers import MDDatePicker
from kivymd.menus import MDDropdownMenu

year1 = 0
monthlist = ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь',]
monthnum = 0
selected_date = ''

class Manager(ScreenManager):
    def __init__(self, **kwargs):
        super(Manager, self).__init__(**kwargs)

class MainMenu(Screen):
    pass

class InfoMenu(Screen):
    pass

class ListButton(MDRaisedButton):
    pass

class DateSetupMenu(Screen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.menu_items = [
                {
                    "viewclass": "MDMenuItem",
                    "text": "%d" % i,
                    "callback": self.callbackforlist,
                }
                for i in range(1900, 2100)
            ]

    def callbackforlist(self, *args):
        pass

class Year_layout_popup1(GridLayout):
    pass

class Year_layout_scrollview1(ScrollView):
    pass

class YearButton1(MDRaisedButton):
    pass

class YearSelectionButton(MDRoundFlatButton):
    def on_release(self):
        global year1
        year1 = int(self.text)

class DatePickPopup(Popup):
    pass

class Month_layout_popup(GridLayout):
    pass

class Month_layout_scrollview(ScrollView):
    pass

class MonthButton(MDRaisedButton):
    pass

class DatePickerWidget(MDDatePicker):   
    pass

class MonthSelectionButton(MDRoundFlatButton):
    def on_release(self):
        global monthlist
        global monthnum
        monthnum = int(monthlist.index(str(self.text)))
        monthnum += 1

class MonthPickPopup(Popup):
    pass

class yearselectbtn(Button):
    pass

class monthselectbtn(Button):
    pass

class rt_android(App):
    theme_cls = ThemeManager()
    theme_cls.device_orientation == 'portrait'
    title = 'Rectif Tattva Android Edition'
    yearselectlabeltext = StringProperty('Выберите год рождения')
    monthselectlabeltext = StringProperty('Выберите месяц рождения')
    dateselectlabeltext = StringProperty('Выберите день рождения')
    mlist = ['Месяц','Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь']
    VARIABLE = ""
    def build(self):
        self.theme_cls.theme_style = 'Light'
        Window.size = (480, 854)
        return Manager()

    def CloseExitPopup(self, *args):
        from kivymd.toast.kivytoast import toast
        if args[0] == 'Да':
            App.get_running_app().stop()
        else:
            pass

    def ExitDialog(self):
        self.dialog = MDDialog(
            title='Выход из приложения', size_hint=(.8, .25), text_button_ok='Нет',
            text="Вы точно хотите выйти?",
            text_button_cancel='Да',
            events_callback=self.CloseExitPopup)
        self.dialog.open()

    def OpenDatePicker(self, *args):
        DatePickerWidget(self.set_date, year1, monthnum, 1).open()

    def set_date(self, date_obj):
        global selected_date
        global year1
        global monthnum
        global daynum
        self.setupdate = date_obj
        selected_date = str(self.setupdate)
        year1 = int(selected_date[0:4])
        monthnum = int(selected_date[5:7])
        daynum = int(selected_date[8:10])
        month_id = monthnum-1

    def year_select_clicked1(self):
        self.ylp = Year_layout_popup1()
        self.ylp.bind(minimum_height=self.ylp.setter('height'))

        # for i in range(1950, 2019):
        #   self.ysb = YearSelectionButton()
        #   self.ysb.text = str(i)
        #   self.ylp.add_widget(self.ysb)

        for i in range(1950, 2019):
            self.ysb = yearselectbtn()
            self.ysb.text = str(i)
            self.ylp.add_widget(self.ysb)

        root = Year_layout_scrollview1()
        root.add_widget(self.ylp)
        self.popup = DatePickPopup()
        self.popup.content = root
        self.popup.open()

    def month_select_clicked(self):
        global monthlist
        self.mlp = Month_layout_popup()
        self.mlp.bind(minimum_height=self.mlp.setter('height'))

        # for i in range(0, 12):
        #   self.msb = MonthSelectionButton()
        #   self.msb.text = str(monthlist[i])
        #   self.msb.id = str(i)
        #   self.mlp.add_widget(self.msb)

        for i in range(0, 12):
            self.msb = monthselectbtn()
            self.msb.text = str(monthlist[i])
            self.msb.id = str(i)
            self.mlp.add_widget(self.msb)

        root = Month_layout_scrollview()
        root.add_widget(self.mlp)
        self.popup_m = DatePickPopup()
        self.popup_m.content = root
        self.popup_m.open()

    def closeitpls(self):
        self.popup.dismiss()

    def closeitpls_m(self):
        self.popup_m.dismiss()

    def change_variable(self, value):
        print("\nvalue=", value)
        self.VARIABLE = value
        print("\tself.VARIABLE=", self.VARIABLE)

class CreditsImage(Image):
    pass

with open("main_interface.kv", encoding='utf8') as f:
    main_interface = Builder.load_string(f.read())

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

还有我的main_interface.kv:

 # encoding=utf8 
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import Factory kivy.factory.Factory
#:import MDLabel kivymd.label.MDLabel
#:import MDRaisedButton kivymd.button.MDRaisedButton
#:import MDRectangleFlatButton kivymd.button.MDRectangleFlatButton
#:import MDToolbar kivymd.toolbar.MDToolbar
#:import MDRoundFlatButton kivymd.button.MDRoundFlatButton
#:import MDDropdownMenu kivymd.menus.MDDropdownMenu
#:import MDMenuItem kivymd.menus.MDMenuItem
#:import hex kivy.utils.get_color_from_hex
#:set white hex('#00a86b')

<MenuButton@MDRaisedButton>:
    font_size: dp(8)
    elevation_normal: 3
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint_x: 0.5
    height: dp(50)

<InfoMenuButton@MDRaisedButton>:
    font_size: dp(8)
    elevation_normal: 3
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: None, None
    height: dp(50)

<DateSetupMenuButton@MDRaisedButton>:
    font_size: dp(8)
    elevation_normal: 3
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: None, None
    height: dp(50)

<Year_layout_popup1>:
    cols: 1
    spacing: 15
    padding: [10,10,10,10]
    size_hint_y: None

<Year_layout_scrollview1>:
    size_hint: (1, None)
    size: Window.width*0.8, Window.height*0.7

<YearButton1>:
    font_size: dp(8)
    elevation_normal: 3
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: None, None
    height: dp(50)

<DatePickPopup>:
    title: 'Выбор года рождения'
    size_hint: 0.8, 0.8
    auto_dismiss: False
    separator_color: white
    title_color: white
    background: 'assets/whiteback.png'

<YearSelectionButton>:
    font_size: dp(8)
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: 1, None
    height: dp(50)
    on_press:
        app.yearselectlabeltext = self.text
    on_release:
        app.closeitpls()

<Month_layout_popup>:
    cols: 1
    spacing: 15
    padding: [10,10,10,10]
    size_hint_y: None

<Month_layout_scrollview>:
    size_hint: (1, None)
    size: Window.width*0.8, Window.height*0.7

<MonthButton>:
    font_size: dp(8)
    elevation_normal: 3
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: None, None
    height: dp(50)

<MonthPickPopup>:
    title: 'Выбор месяца рождения'
    size_hint: 0.8, 0.8
    auto_dismiss: False
    separator_color: white
    title_color: white
    background: 'assets/whiteback.png'

<MonthSelectionButton>:
    id: ''
    font_size: dp(8)
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: 1, None
    height: dp(50)
    on_press:
        app.monthselectlabeltext = self.text
    on_release:
        app.closeitpls_m()

<yearselectbtn>:
    font_size: dp(16)
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: 1, None
    height: dp(50)
    background_color: (255, 255, 255, 1)
    color: (0,0,0,1)
    on_press:
        app.yearselectlabeltext = self.text
    on_release:
        app.closeitpls()

<monthselectbtn>:
    font_size: dp(16)
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: 1, None
    height: dp(50)
    background_color: (255, 255, 255, 1)
    color: (0,0,0,1)
    on_press:
        app.monthselectlabeltext = self.text
    on_release:
        app.closeitpls_m()

<MDMenuItem>:
    on_release:
        app.root.ids.buttonoflist.text = self.text

<ListButton>:
    id: buttonoflist
    font_size: dp(8)
    pos_hint: {'center_x': .5, 'center_y': .5}
    size_hint: None, None
    height: dp(50)

<Manager>:
    MainMenu:
        name: 'main_menu'   
    InfoMenu:
        name: 'info_menu'
    DateSetupMenu:
        name: 'date_setup_menu'

<MainMenu>:
    AnchorLayout:
        anchor_y: 'top'
        MDToolbar:
            title: app.title
            elevation: 10
            md_bg_color: white
    AnchorLayout:
        anchor_y: 'bottom'
        BoxLayout:
            orientation: 'vertical'
            size_hint: 0.95, 0.25
            spacing: dp(10)
            padding: [0, 0, 0, dp(10)]
            MenuButton:
                text: 'Приступить'
                on_press:
                    app.root.transition = SlideTransition(direction='left', duration = .17)
                on_release:
                    root.manager.current = 'date_setup_menu'
            MenuButton:
                text: 'Инфо'
                on_press:
                    app.root.transition = SlideTransition(direction='left', duration = .17)
                on_release:
                    root.manager.current = 'info_menu'
            MenuButton:
                text: 'Выход'
                on_release:
                    app.ExitDialog()

<InfoMenu>:
    AnchorLayout:
        anchor_y: 'top'
        MDToolbar:
            title: 'Инфо'
            elevation: 10
            md_bg_color: white
        BoxLayout:
            size_hint_y: 0.4
            orientation: 'vertical'
            spacing: 5
            padding: [0, dp(90), 0, 0]
            pos_hint: {'center_x': .5, 'center_y': 1}
            CreditsImage:
                source: 'assets/info_credits_table.png'
                size_hint_y: 0.8
            MDLabel:
                text: 'версия программы: 1.0.0'
                font_name: 'assets/Ponter.ttf'
                color: (255,255,255,1)
                size_hint_y: 0.2
                font_size: dp(20)
                halign: 'center'
                valign: 'top'
                text_size: self.size                
    AnchorLayout:
        anchor_y: 'bottom'
        BoxLayout:
            orientation: 'vertical'
            size_hint: 0.95, 0.25
            padding: [0, 0, 0, dp(15)]
            InfoMenuButton:
                text: 'Назад'
                on_press:
                    app.root.transition = SlideTransition(direction='right', duration = .17)
                on_release:
                    root.manager.current = 'main_menu'

<DateSetupMenu>:
    AnchorLayout:
        anchor_y: 'top'
        MDToolbar:
            title: 'Выбор параметров'
            elevation: 10
            md_bg_color: white
    AnchorLayout:
        anchor_y: 'center'
        BoxLayout:
            orientation: 'vertical'
            size_hint: 0.95, 0.25
            padding: [0, dp(15), 0, 0]
            spacing: dp(5)
            ListButton:
                id: buttonoflist
                text: 'Выбор'
                on_release:
                    MDDropdownMenu(items=root.menu_items, width_mult=4).open(self)
            YearButton1:
                text: app.yearselectlabeltext
                on_release:
                    app.year_select_clicked1()
            MonthButton:
                text: app.monthselectlabeltext
                on_release:
                    app.month_select_clicked()
            DateSetupMenuButton:
                text: app.dateselectlabeltext
                on_release:
                    app.OpenDatePicker()
        AnchorLayout:
            anchor_y: 'bottom'
            BoxLayout:
                orientation: 'vertical'
                size_hint: 0.95, 0.25
                padding: [0, 0, 0, dp(15)]
                DateSetupMenuButton:
                    text: 'Назад'
                    on_press:
                        app.root.transition = SlideTransition(direction='right', duration = .17)
                    on_release:
                        root.manager.current = 'main_menu'

我需要在正确单击MDMenuItem后更改«ListButton»对象的文本。我不知道为什么它可以在独立代码中工作,但是在我的主要代码中却有一个可怕的问题……

1 个答案:

答案 0 :(得分:1)

错误-KeyError和AttributeError

 Traceback (most recent call last):
   File "kivy/properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'buttonoflist'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   ...
   File ".../main.kv", line 132, in <module>
     app.root.ids.buttonoflist.text = self.text
   File "kivy/properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

根本原因

遇到的第一个错误是KeyError,因为id'buttonoflist'在Kivy self.ids字典类型属性中不存在。

遇到的第二个错误是AttributeError,因为id(“ buttonoflist”)在根(即ScreenManager)中不存在。

解决方案

  1. 由于在屏幕中声明了id: buttonoflistDateSetupMenu:,您必须将一个ID添加到DateSetupMenu对象,以便 您可以访问/引用它。
  2. app.root.ids.buttonoflist.text替换为app.root.ids.date_setup_menu.ids.buttonoflist.text

摘要-kv文件

<MDMenuItem>:
    on_release:
        app.root.ids.date_setup_menu.ids.buttonoflist.text = self.text

...

<Manager>:
    ...
    DateSetupMenu:
        id: date_setup_menu
        name: 'date_setup_menu'
...

输出

Year Dropdown - before selection Year Dropdown - after selection