Search code examples
pythonkivykivymd

Python KivyMD - input from one screen, display output in another screen


I want to make a 2 page Kivy app - input a word, output definition on another screen. I tried Kivy, it worked. Now I used KivyMD. I encountered NameError.

   Traceback (most recent call last):
   File "C:/Users/Andrew/PycharmProjects/JesscarlettApp/dictapp.py", line 94, in <module>
     TestApp().run()
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\app.py", line 950, in run
     runTouchApp()
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\base.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\base.py", line 347, in mainloop
     self.idle()
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\base.py", line 391, in idle
     self.dispatch_input()
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\base.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\base.py", line 308, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivymd\uix\behaviors\ripplebehavior.py", line 245, in on_touch_up
     return super().on_touch_up(touch)
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivymd\uix\button.py", line 969, in on_touch_up
     return super().on_touch_up(touch)
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
   File "C:\Users\Andrew\PycharmProjects\JesscarlettApp\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "<string>", line 24, in <module>
 NameError: name 'meaning' is not defined

This is my main.py and kv. (please ignore those additional unused modules.) The issue is of this line "meaning.text = app.show_data_meaning()" in the kv. But I just don't know how to fix it. Many thanks.

from kivy.app import App
from kivymd.uix.screen import Screen
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
from kivy.uix.label import Label
from kivymd.uix.button import MDRectangleFlatButton
from kivy.core.window import Window
from kivy.uix.image import Image, AsyncImage
from kivymd.app import MDApp
from PyDictionary import PyDictionary
from bs4 import BeautifulSoup as bs
from kivymd.uix.label import MDLabel


class WordScreen(Screen):
    pass


class MeaningScreen(Screen):
    pass


screen_helper = """
ScreenManager:
    id: screen_manager
    
    WordScreen:
    MeaningScreen:

<WordScreen>
    name: 'wordscreen'
    MDTextField:
        hint_text: "Word"
        id: text_field
        text:'default'
        icon_right: "dictionary"
        icon_right_color: app.theme_cls.primary_color
        pos_hint: {'center_x':0.5, 'center_y':0.9}
        size_hint_x:None
        width:300
    MDRectangleFlatButton:
        text: 'search'
        id: search_button
        pos_hint: {'center_x': 0.5, 'center_y': 0.8}
        on_release: 
            meaning.text = app.show_data_meaning()
            root.manager.current = 'meaningscreen'
            
<MeaningScreen>
    name: 'meaningscreen'
    MDRectangleFlatButton:
        text: 'back'
        pos_hint: {'center_x': 0.5, 'center_y': 0.2}
        on_release: root.manager.current = 'wordscreen' 
    MDLabel:
        text: "Default"
        id: meaning
        halign: 'center'
        theme_text_color: 'Secondary'
        font_style: 'Body1'
        pos_hint: {'center_x': 0.5, 'center_y': 0.6} 

"""

class TestApp(MDApp):
    def __init__(self, **kwargs):
        self.title = "Dictionary App"
        self.theme_cls.primary_palette = "Blue"
        super().__init__(**kwargs)

    def build(self):
        sm = Builder.load_string(screen_helper)
        return sm

    def show_data_meaning(self):
        searchword = self.root.get_screen("wordscreen").ids.text_field.text
        print(searchword)
        dictionary = PyDictionary(searchword)
        meaning = dictionary.getMeanings()
        print(meaning)
        return meaning


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

Solution

  • You can make a new method in your TestApp to set the text on the next screen

    example:

        def my_func(self):
            self.root.get_screen("meaningscreen").ids.meaning.text = str(self.show_data_meaning())
    

    and call your method in button release

    on_release: 
            app.my_func()
            root.manager.current = 'meaningscreen'
    

    you can also do this in kv file as well, you just need to get meaningscreen then meaningscreen.ids.text_field.meaning.text = app.show_data_meaning()

    here is your code after changes

    from kivy.app import App
    from kivymd.uix.screen import Screen
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivymd.uix.textfield import MDTextField
    from kivy.lang import Builder
    from kivy.uix.label import Label
    from kivymd.uix.button import MDRectangleFlatButton
    from kivy.core.window import Window
    from kivy.uix.image import Image, AsyncImage
    from kivymd.app import MDApp
    from PyDictionary import PyDictionary
    from bs4 import BeautifulSoup as bs
    from kivymd.uix.label import MDLabel
    
    
    class WordScreen(Screen):
        pass
    
    
    class MeaningScreen(Screen):
        pass
    
    
    screen_helper = """
    ScreenManager:
        id: screen_manager
    
        WordScreen:
        MeaningScreen:
    
    <WordScreen>
        name: 'wordscreen'
        MDTextField:
            hint_text: "Word"
            id: text_field
            text:'default'
            icon_right: "dictionary"
            icon_right_color: app.theme_cls.primary_color
            pos_hint: {'center_x':0.5, 'center_y':0.9}
            size_hint_x:None
            width:300
        MDRectangleFlatButton:
            text: 'search'
            id: search_button
            pos_hint: {'center_x': 0.5, 'center_y': 0.8}
            on_release: 
                app.my_func()
                root.manager.current = 'meaningscreen'
    
    <MeaningScreen>
        name: 'meaningscreen'
        MDRectangleFlatButton:
            text: 'back'
            pos_hint: {'center_x': 0.5, 'center_y': 0.2}
            on_release: root.manager.current = 'wordscreen' 
        MDLabel:
            text: "Default"
            id: meaning
            halign: 'center'
            theme_text_color: 'Secondary'
            font_style: 'Body1'
            pos_hint: {'center_x': 0.5, 'center_y': 0.6} 
    
    """
    
    
    class TestApp(MDApp):
        def __init__(self, **kwargs):
            self.title = "Dictionary App"
            self.theme_cls.primary_palette = "Blue"
            super().__init__(**kwargs)
    
        def build(self):
            sm = Builder.load_string(screen_helper)
            return sm
    
        def show_data_meaning(self):
            searchword = self.root.get_screen("wordscreen").ids.text_field.text
            print(searchword)
            dictionary = PyDictionary(searchword)
            meaning = dictionary.getMeanings()
            print(meaning)
            return meaning
    
        def my_func(self):
            self.root.get_screen("meaningscreen").ids.meaning.text = str(self.show_data_meaning())
    
    
    if __name__ == '__main__':
        TestApp().run()