Kivy MD DropDownItem: how to set the item of a dropdownitem into another dropdownitem

huangapple go评论76阅读模式
英文:

Kivy MD DropDownItem: how to set the item of a dropdownitem into another dropdownitem

问题

  1. The AttributeError: 'super' object has no attribute '__getattr__' error in the second version of your code is likely caused by the incorrect use of the super() function in the View class. You should call super() with the class and instance as arguments. Change this line in your View class constructor:

    super().__init__(**kwargs)
    

    to:

    super(View, self).__init__(**kwargs)
    

    This should resolve the AttributeError issue.

  2. To set the items of two dropdown items equal to each other, you can create a method in your MainApp class that updates both dropdown items when one is selected. Here's an example of how you can do it:

    def update_dropdown_items(self, selected_item):
        self.view.ids.drop_item_1.set_item(selected_item)
        self.view.menu_sampling_rate_1.dismiss()
        self.view.ids.drop_item_2.set_item(selected_item)
        self.view.menu_sampling_rate_2.dismiss()
    

    You can call this method when a dropdown item is selected.

  3. To set the width of a dropdown item to dp(80), you should use the width property of the MDDropdownMenu widget when creating it. For example, in your Create_DropDown_Widget function, modify the menu = MDDropdownMenu(...) line like this:

    menu = MDDropdownMenu(caller=drop_down_item, items=items_collection, width=dp(80))
    

    This will set the width of the dropdown menu to dp(80).

  4. To enable or disable a dropdown item, you can use the disabled property. You can set it to True to disable the dropdown item and False to enable it. For example:

    To disable a dropdown item:

    self.view.ids.drop_item_1.disabled = True
    

    To enable a dropdown item:

    self.view.ids.drop_item_1.disabled = False
    

    Setting the disabled property to True will gray out the dropdown item and make it unselectable.

英文:

I'm trying to developed a simple GUI in Kivy MD / Python. Originally, I modified the example code:

from kivy.lang import Builder
from kivy.metrics import dp
from kivymd.uix.list import OneLineIconListItem
from kivymd.app import MDApp
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.dropdownitem import MDDropDownItem
from kivymd.uix.boxlayout import MDBoxLayout

KV = '''
MDScreen

   MDDropDownItem:
       id: drop_item_1
       pos_hint: {'center_x': .5, 'center_y': .8}
       text: 'FREQUENCY_1'
       on_release: app.menu_sampling_rate_1.open()
       
   MDDropDownItem:
       id: drop_item_2
       pos_hint: {'center_x': .5, 'center_y': .4}
       text: 'FREQUENCY_2'
       on_release: app.menu_sampling_rate_2.open()
'''


class MainApp(MDApp):
   sampling_rate = ['300 Hz', '200 Hz', '100 Hz']   
   
   def __init__(self, **kwargs):
       super().__init__(**kwargs)
       self.screen = Builder.load_string(KV)
       
       self.menu_sampling_rate_1, self.sampling_rate_items_1 = self.Create_DropDown_Widget(self.screen.ids.drop_item_1, self.sampling_rate)
       self.menu_sampling_rate_2, self.sampling_rate_items_2 = self.Create_DropDown_Widget(self.screen.ids.drop_item_2, self.sampling_rate)
               
   
   def Create_DropDown_Widget(self, drop_down_item, item_list):
       items_collection = [
           {
               "viewclass": "OneLineListItem",
               "text": item_list[i],
               "height": dp(56),
               "on_release": lambda x = item_list[i]: self.Set_DropDown_Item(drop_down_item, menu, x),
           } for i in range(len(item_list))
       ]
       
       menu = MDDropdownMenu(caller=drop_down_item, items=items_collection, width_mult=2)
       menu.bind()
       
       return menu, items_collection


   def Set_DropDown_Item(self, dropDownItem, dropDownMenu, textItem):
       dropDownItem.set_item(textItem)
       dropDownMenu.dismiss()  


   def build(self):
       return self.screen


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

I tried to slightly modify it using a class View in which all methods and properties related to the interface are included.

from kivy.lang import Builder
from kivy.metrics import dp
from kivymd.uix.list import OneLineIconListItem
from kivymd.app import MDApp
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.dropdownitem import MDDropDownItem
from kivymd.uix.boxlayout import MDBoxLayout

KV = '''
<View>:
    orientation: vertical

    MDDropDownItem:
        id: drop_item_1
        pos_hint: {'center_x': .5, 'center_y': .8}
        text: 'FREQUENCY_1'
        on_release: root.menu_sampling_rate_1.open()
        
    MDDropDownItem:
        id: drop_item_2
        pos_hint: {'center_x': .5, 'center_y': .4}
        text: 'FREQUENCY_2'
        on_release: root.menu_sampling_rate_2.open()
'''



class View(MDBoxLayout):
    sampling_rate = ['300 Hz', '200 Hz', '100 Hz']      
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        self.menu_sampling_rate_1, self.sampling_rate_items_1 = self.Create_DropDown_Widget(self.ids.drop_item_1, self.sampling_rate)
        self.menu_sampling_rate_2, self.sampling_rate_items_2 = self.Create_DropDown_Widget(self.ids.drop_item_2, self.sampling_rate)
        
                
    def Create_DropDown_Widget(self, drop_down_item, item_list):
        items_collection = [
            {
                "viewclass": "OneLineListItem",
                "text": item_list[i],
                "height": dp(56),
                "on_release": lambda x = item_list[i]: self.Set_DropDown_Item(drop_down_item, menu, x),
            } for i in range(len(item_list))
        ]
        
        menu = MDDropdownMenu(caller=drop_down_item, items=items_collection, width_mult=2)
        menu.bind()
        
        return menu, items_collection    
    

    def Set_DropDown_Item(self, dropDownItem, dropDownMenu, textItem):
        dropDownItem.set_item(textItem)
        dropDownMenu.dismiss()   


class MainApp(MDApp):    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.view = View()

    def build(self):
        return self.view


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

My questions are:

  1. In this second version, with the View class, why I get the AttributeError: 'super' object has no attribute 'getattr'?
  2. How to set the item of a dropdownitem equal to the current item of the second dropdownitem and viceversa? In this way when the user selects a new item into a dropdownitem, this new selection appears also into the other dropdownitem.So the two dropdownitem show the same current item.
  3. How to set the width of a dropdownitem equal to dp(80)? The approach based on size_hint_x and width seems to not work.
  4. Is there a way to enable/disable a dropdownitem? The property active seems to not work.

Thank you in advance for any suggestions.

答案1

得分: 1

  • 因为在执行 View(MDBoxLayout) 类的 __init__ 时,self.ids 中没有任何内容,所以会出现 AttributeError: 'super' object has no attribute 'getattr' 错误。

  • 如果您想要将一个下拉菜单项的项目设置为另一个下拉菜单项的当前项目,可以使用 ids 来更改它们。以下是一个可能的实现示例:

def Set_DropDown_Item(self, dropDownMenu, textItem):
    wanted_dropdowns = ('drop_item_1', 'drop_item_2')  # 您想要修改的小部件的ids
    for dropdown in wanted_dropdowns:
        self.screen.ids[dropdown].set_item(textItem)
    dropDownMenu.dismiss()
  • 要将下拉菜单项的宽度设置为 dp(80),您可以尝试将字体大小 font_size 设置为 "80dp"

  • 如果要启用/禁用一个下拉菜单项,可以使用 disabled 属性。在 Python 中,您可以这样做:

def disable_widget(self, widget):
    widget.disabled = True

在 Kv 文件中,您可以这样使用:

disabled: 'True'
英文:

> In this second version, with the View class, why I get the
> AttributeError: 'super' object has no attribute 'getattr'?

Because at the moment of executing init of class View(MDBoxLayout) you dont have anything in self.ids

If you try it in debug you will see it:
Kivy MD DropDownItem: how to set the item of a dropdownitem into another dropdownitem

Solution here to create widgets after Kivy created own objects, in you first example you do it in MainApp class and thats ok.

> How to set the item of a dropdownitem equal to the current item of the
> second dropdownitem and viceversa? In this way when the user selects a
> new item into a dropdownitem, this new selection appears also into the
> other dropdownitem.So the two dropdownitem show the same current item.

If you want to change another widget(s) - just use ids to change them after you changed first one. Example of possible implementation:

    def Set_DropDown_Item(self, dropDownMenu, textItem):
       wanted_dropdowns = ('drop_item_1', 'drop_item_2')  # ids of widgets you want to modify
       for dropdown in wanted_dropdowns:
           self.screen.ids[dropdown].set_item(textItem)
       dropDownMenu.dismiss()

> How to set the width of a dropdownitem equal to dp(80)? The approach
> based on size_hint_x and width seems to not work.

Widget size changes to fit text, so maybe font_size: "80dp" is what you want.

Kivy MD DropDownItem: how to set the item of a dropdownitem into another dropdownitem

> Is there a way to enable/disable a dropdownitem? The property active
> seems to not work.

Use disabled property. In python:

    def disable_widget(self, widget):
       widget.disabled = True

In kv

  disabled: 'True'

huangapple
  • 本文由 发表于 2023年2月8日 21:55:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75386804.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定