英文:
Kivy MD DropDownItem: how to set the item of a dropdownitem into another dropdownitem
问题
-
The
AttributeError: 'super' object has no attribute '__getattr__'
error in the second version of your code is likely caused by the incorrect use of thesuper()
function in theView
class. You should callsuper()
with the class and instance as arguments. Change this line in yourView
class constructor:super().__init__(**kwargs)
to:
super(View, self).__init__(**kwargs)
This should resolve the
AttributeError
issue. -
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.
-
To set the width of a dropdown item to
dp(80)
, you should use thewidth
property of theMDDropdownMenu
widget when creating it. For example, in yourCreate_DropDown_Widget
function, modify themenu = 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)
. -
To enable or disable a dropdown item, you can use the
disabled
property. You can set it toTrue
to disable the dropdown item andFalse
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 toTrue
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:
- In this second version, with the View class, why I get the AttributeError: 'super' object has no attribute 'getattr'?
- 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.
- 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.
- 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:
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.
> 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'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论