Search code examples
pythonkivykivy-languagenameerror

Python Kivy Dyanmic Class not defined


I keep getting a Name Error reporting "name TripButton is not defined" although I have a button called TripButton defined in the same .kv file.

#:kivy 1.11.1

<TripButton@Button>:
    size_hint: (0.15,0.15)
    pos_hint: {'y':0.84}
    text:"Test Text"

<MyPopup>:
    size_hint: 0.5, 0.5
    auto_dismiss: False
    title: 'New Trip'

    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: trip_name
            multiline: False

        BoxLayout:
            size_hint_y: None
            height: 30

            Button:
                text: 'Submit'
                on_release:
                    root.parent.parent.add_widget(TripButton(text=trip_name.text, size_hint=(1,0.1)))
                    root.dismiss()

            Button:
                text: 'Cancel'
                on_release: root.dismiss()


<FirstScreen>:
    name: 'first'
    FloatLayout:

        BoxLayout:
            size_hint: (0.95, 0.95)
            pos_hint: {'center_x':0.5, 'center_y':0.5}
            orientation: "vertical"

            canvas.before:
                Color:
                    rgba: (1, 0, 0, 1) # Red color

                Rectangle:
                    pos: self.pos
                    size: self.size
            BoxLayout:
                TripButton:


            Button:
                text: 'Add Trip'
                font_size: 12
                size_hint: (0.1, 0.1)
                pos_hint: {'right':1, 'bottom':1}
                on_release: app.open_popup()
                pos_hint: {'right':1, 'bottom':1}
                on_release: app.open_popup()

I tried declaring the TripButton class above and below the MyPopup class and that didn't work. I compared my code with the kivy documentation for dynamic classes and the from what I can tell I'm matching the syntax. I tried importing the Button class in both the python file and the .kv file and that hasn't worked.

To clarify all of this is in the same .kv file in the same directory as the python file. the app runs until I click the submit button in MyPopup then the program crashes and I get the NameError. This is what I have in my python file.

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup

class FirstScreen(Screen):
    pass

class MyPopup(Popup):
    pass

class MyApp(App):

    def build(self):
        sm = ScreenManager()
        sm.add_widget(FirstScreen(name='first'))
        sm.current = 'first'
        return sm

    def open_popup(self):
        p = MyPopup()
        p.open()

    def add_button(self):
        pass


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

What am I doing wrong? What else I can try? Thanks for your time.


Solution

  • To access classes defined within kv file use kivy.factory.Factory

    Add id attribute to your button's BoxLayout, so replace following part of kv file:

            BoxLayout:
                TripButton:
    

    with

            BoxLayout:
                id: trip_buttons
                TripButton:
    

    then replace:

    root.parent.parent.add_widget(TripButton(text=trip_name.text, size_hint=(1,0.1)))
    

    with:

    app.root.current_screen.ids.trip_buttons.add_widget(kivy.factory.Factory.TripButton(text=trip_name.text, size_hint=(1,0.1)))
    

    You also duplicated following lines within last button definition on first screen. Replace:

                pos_hint: {'right':1, 'bottom':1}
                on_release: app.open_popup()
                pos_hint: {'right':1, 'bottom':1}
                on_release: app.open_popup()
    

    with

                pos_hint: {'right':1, 'bottom':1}
                on_release: app.open_popup()