Search code examples
pythonkivykivy-languagekivymd

How to dynamically change a textfield in a MDDialog KivyMD?


I need to capture some product information in a dialog box to feed a MDList, the user has to entry the product code and there's a disabled textfield where I want the name of the product to show, I'd like to show this name dynamically in its textfield when a different code is introduced. The codes and names are related in a dictionary.

Do I have to approach this from the kv file or from the py file?

Here's a similar app to what I need:

PY

from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDRaisedButton, MDFlatButton
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.list import TwoLineListItem
from kivymd.uix.snackbar import Snackbar



product_dict={'1': 'name 1', '2': 'name 2', '3': 'name 3'}
product_dict_values=list(product_dict.values())
product_dict_keys=list(product_dict.keys())

class MainWindow(Screen):
    pass

class SecondWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class DialogContent(BoxLayout):
    pass

class MainApp(MDApp):

    dialog=None

    def build(self):
        self.theme_cls.theme_style="Dark"
        self.theme_cls.primary_palette="Green"
        return Builder.load_file('exam.kv')




    def close_dialog(self, obj):
        self.dialog.dismiss()

    def confirm_selection(self, obj):
        #check number in quantity field

        if self.dialog.content_cls.ids.code.text not in product_dict_keys:
            self.dialog.content_cls.ids.code.text=""
            Snackbar(text='Code not in product_dict').open()

        else:
            self.root.get_screen('main').ids.list.add_widget(
                TwoLineListItem(text=f'Name: {self.dialog.content_cls.ids.name.text}',
                    secondary_text=f'Code: {self.dialog.content_cls.ids.code.text}'

                )
            )
            #clear text fields after confirmation
            self.dialog.content_cls.ids.name.text=""
            self.dialog.content_cls.ids.code.text=""

            Snackbar(text='Success').open()

    def show_dialog(self):

        if not self.dialog:
            self.dialog=MDDialog(
                title='Add details',
                type='custom',
                content_cls=DialogContent(),
                buttons=[
                    MDFlatButton(
                        text='CANCEL',
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        on_release=self.close_dialog
                    ),
                    MDRaisedButton(
                        text='OK',
                        theme_text_color="Custom",
                        on_release=
                            self.confirm_selection

                    )
                ],
            )
        self.dialog.open()


MainApp().run()

KV

WindowManager:
    MainWindow:
    SecondWindow:

<DialogContent>
    id: dialog
    orientation: "vertical"
    spacing: "10dp"
    size_hint_y: None
    height: "160dp"


    MDTextField:
        id: name
        text: self.text #self.text if code.text is None else product_dict[code.text]
        disabled: True
        hint_text: "Name"
        #required: True


    MDTextField:
        id: code
        hint_text: "Code"
        required: True



<MainWindow>
    name: 'main'
    MDBoxLayout:
        orientation: 'vertical'
        MDToolbar:
            title: 'test'



        MDBoxLayout:
            orientation:'vertical'
            spacing: dp(10)
            padding: dp(20)


            MDRaisedButton:
                text: 'fill'
                on_release:
                    app.show_dialog()


            AnchorLayout:
                adaptive_height:True
                ScrollView:
                    MDList:
                        id: list

Solution

  • You need to connect your DialogContent BoxLayout from .kv file to .py file.For that, we need to use ObjectProperty. Now, we can check written code.

    .py file:

    from kivy.properties import ObjectProperty()
    ........
    class DialogContent(BoxLayout):
        name = ObjectProperty()
        def texting(self,text):
            if text == '':
                self.name.text=''
            else:
                for key,value in product_dict.items():
                    if text == key:
                        self.name.text = product_dict[text]
                        break
                else:
                    self.name.text = '(Code not Valid)'
    ........
    

    .kv file:

    ........
    <DialogContent>
        name:name
        id: dialog
        orientation: "vertical"
        spacing: "10dp"
        size_hint_y: None
        height: "160dp"
        
        MDTextField:
            id: name
            text: self.text #self.text if code.text is None else product_dict[code.text]
            disabled: True
            hint_text: "Name"
            #required: True
    
        MDTextField:
            id: code
            hint_text: "Code"
            required: True
            on_text: root.texting(self.text)
    ........