How to pass text from .py file into .kv widget?

Viewed 37

Hi I recently started developing emotion detection app using kivy. I want to display the detected emotion on the main screen but I don't know how to take detected emotion (text) and pass it to the .kv file. The code is very long so I shared the necessary part only. How do I take the emotion from self.label and pass it to root.text in display_emotion?

This is my .py file

class DipxyApp(MDApp):   
    def build(self):        
        Window.size = (350, 600)
        self.theme_cls.theme_style = 'Dark'
        self.theme_cls.primary_palette = 'Purple'
        self.theme_cls.accent_palette = 'Purple'
        self.theme_cls.primary_hue = '800'
        self.theme_cls.accent_hue = '400'
        self.title = 'Dipxy'
        screen = Builder.load_file('dipxy.kv')

        # storing all the screens in a list
        screens = [
            LandingScreen(name='landing_screen'),
            LoginScreen(name='login_screen'),
            SignupScreen(name='signup_screen'),
            MainScreen(name='main_screen'),
            ProfileScreen(name='profile_screen'),
            EditUsernameScreen(name='edit_username_screen'),
            EditEmailScreen(name='edit_email_screen'),
            EditPasswordScreen(name='edit_password_screen'),
            PlaylistScreen(name='playlist_screen'),
        ]

        # adding all screen in screens to window manager
        self.wm = WindowManager(transition=FadeTransition())
        for screen in screens:
            self.wm.add_widget(screen)

        return self.wm

    def detect_emotion(self, *args):
        self.vs = VideoStream(src=0).start()
        Clock.schedule_interval(self.load_video, 1.0 / 30.0)

    def load_video(self, *args):
        self.frame = self.vs.read()
        frame = imutils.resize(self.frame, height=480, width=640)

        (h, w) = frame.shape[:2]
        blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))

        net.setInput(blob)
        detections = net.forward()

         for i in range(0, detections.shape[2]):
            confidence = detections[0, 0, i, 2]

            if confidence > CONFIDENCE:
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                (startX, startY, endX, endY) = box.astype("int")

                startX = max(0, startX)
                startY = max(0, startY)
                endX = min(w, endX)
                endY = min(h, endY)

                face = frame[startY:endY, startX:endX]
                face = cv2.resize(face, (32, 32))
                face = face.astype("float") / 255.0
                face = img_to_array(face)
                face = np.expand_dims(face, axis=0)

                preds = model.predict(face)[0]
                j = np.argmax(preds)
                self.label = le.classes_[j]
                # print(preds) # the highest number of index preds
                # print(j)   # [0 1 2 3 4 5]
                print(self.label)  # angry / fear / happy / neutral / sad / surprised 

And this is my .kv code

<MainScreen>:
    name: "main_screen"
    MDBottomNavigation:
        id: bottom_nav
        panel_color: app.theme_cls.bg_normal
        text_color_active: rgba (135, 135, 193, 255)
        MDBottomNavigationItem:
            name: "home"
            icon: "home-outline"
            text: "Home"
            ScrollView:
                bar_width: 0
                do_scroll_y: True
                do_scroll_x: False
                height: 1200
                # toolbar to display emotion
                MDBoxLayout:
                    orientation: 'vertical'
                    md_bg_color: app.theme_cls.primary_color
                    MDFloatLayout:
                        adaptive_height: True
                        id: emotion_display_box
                        MDLabel:
                            text: "You are feeling,"
                            font_size: 16
                            pos_hint: {"center_x": .6, "center_y": .68}
                        MDLabel:
                            id: display_emotion
                            text: **root.text**
                            font_size: 26
                            bold: True
                            pos_hint: {"center_x": .6, "center_y": .43}
                        MDRoundFlatButton:
                            text:"Capture Emotion"
                            pos_hint: {"center_x": .77, "center_y": .47}
                            line_color: 1, 1, 1, 1
                            on_press:
                                app.detect_emotion()``` 
1 Answers

By using a StringProperty, you can easily accomplish this. Just change your kv to:

                    MDLabel:
                        id: display_emotion
                        text: root.text
                        font_size: 26
                        bold: True
                        pos_hint: {"center_x": .6, "center_y": .43}

Then add a StringProperty to the MainScreen class:

class MainScreen(Screen):
    text = StringProperty('')

Then, anywhere in your code, you can just set the above text property and it will appear in your MDLabel. For example, in your load_video() method:

    main_screen = self.wm.get_screen('main_screen')
    main_screen.text = self.label
Related