Search code examples
pythonpython-3.xkivykivy-language

How to build a MDDropdownMenu and its items on pressing a Button?


As my app has many screens and is almost done building the frontend i dont want to change the screen manager(<root widget>:) and class MainApp(MDApp):. Please help me on how i can add a MDDropdownMenu on pressing package weight button on my home screen without changing the layout of my code. Not only the below mentioned code but i have tried different ways to implement it but faced lots of errors. Please help and Thanks in advance.

MY main.py file

from kivymd.app import MDApp
import json
from datetime import datetime
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from kivy.uix.behaviors import ButtonBehavior
from kivymd.uix.button import MDFlatButton ,MDRectangleFlatIconButton 
from kivymd.uix.label import MDLabel, MDIcon
from kivymd.uix.textfield import MDTextField
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import OneLineListItem
from kivy.core.window import Window
from kivymd.uix.menu import MDDropdownMenu, MDMenuItem

class HomeScreen(Screen):

    def drop(self):
            self.dropdown= MDDropdownMenu(items= {"viewclass": "MDMenuItem","text":"option1"}, width_mult=4)
            self.dropdown.open()
    


class RootWidget(ScreenManager):
    pass


class MainApp(MDApp):
    
    def build(self):
        self.theme_cls.primary_palette= "Green"
        return RootWidget()
    
if __name__ == "__main__":
    MainApp().run() 

My design.kv file

<HomeScreen>:
     GridLayout:
         cols: 1
         padding: 20, 20
         spacing: 10,10
         size_hint: 1,0.87
         MDRectangleFlatIconButton:
             icon: 'weight-kilogram'
             text: "Package weight"
             size_hint: (0.55,1)
             on_press: root.drop()
 <RootWidget>:
     HomeScreen:
         name: "home_screen"

This is the image of my app home screen

enter image description here


Solution

  • You need to include the caller in your MDDropdownMenu() call, and the items is expected to be a list of dictionaries.

    Try changing your kv to include an id for the MDRectangleFlatIconButton:

    <HomeScreen>:
        GridLayout:
            cols: 1
            padding: 20, 20
            spacing: 10,10
            size_hint: 1,0.87
            MDRectangleFlatIconButton:
                id: caller   # ADDED
                icon: 'weight-kilogram'
                text: "Package weight"
                size_hint: (0.55,1)
                on_press: root.drop()
    

    The id is used to identify the caller.

    Then create the DropDown in a on_kv_post() method, and the drop() method just opens the DropDown:

    class HomeScreen(Screen):
        def on_kv_post(self, base_widget):
            caller = self.ids.caller
            self.dropdown = MDDropdownMenu(caller=caller, items=[{"viewclass": "MDMenuItem", "text": "option1"}], width_mult=4)
    
        def drop(self):
            self.dropdown.open()
    

    The on_kv_post() method is executed after the kv rules have been executed, so that the ids are available.

    The MDDropdownMenu is not created in the drop() method, as recommended in the documentation.