0

I am trying to create in instance of ProjectScreen dynamic class when add_project_screen is called. I want to create various instances of ProjectScreen, each with a different name, which is obtained from project_name_text_input. Here are my .py and .kv files:

from kivy.app import App

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.listview import ListItemButton
from kivy.factory import Factory

class ProjectListButton(ListItemButton):
    pass

class HomeScreen(Screen):
    pass

class ProjectListScreen(Screen):
    project_list = ObjectProperty(None)

class ProjectScreen(Screen):
    pass


class NewProjectScreen(Screen):
    project_name_text_input = ObjectProperty(None)
    project_address_text_input = ObjectProperty(None)
    project_scope_text_input = ObjectProperty(None)


    def add_project_list_item(self,project_name_text_input):
        new_project_name = project_name_text_input.text
        project_list_screen = self.manager.get_screen('project_list_screen')
        project_list_screen.project_list.adapter.data.extend([new_project_name])
        # Reset the ListView
        project_list_screen.project_list._trigger_reset_populate()
        #project_name_text_input.text = ''

    def add_project_screen(self,project_name_text_input, project_address_text_input, project_scope_text_input):
        name = project_name_text_input.text
        s = Factory.ProjectScreen(name=name)
        self.manager.add_widget(s)

class ReportingApp(App):
    def build(self):
        screen_manager = ScreenManager()
        screen_manager.add_widget(HomeScreen(name="home_screen"))
        screen_manager.add_widget(ProjectListScreen(name="project_list_screen"))
        screen_manager.add_widget(NewProjectScreen(name="new_project_screen"))
        return screen_manager

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

and here is .kv file:

#:kivy 1.10.1

#: import main main
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import ListItemButton kivy.uix.listview.ListItemButton


<HomeScreen>:
BoxLayout:
    orientation: "vertical"
    padding: 100
    spacing: 25
    Label:
        size_hint_y: None
        height: 150
        text: "Site Visit Reporting App v1.1"

    Button:
        text: "New Project"
        on_press:
            root.manager.transition.direction = 'left'
            root.manager.current = 'new_project_screen'

    Button:
        text: "Project List"
        on_press:
            root.manager.transition.direction = 'left'
            root.manager.current = 'project_list_screen'

<NewProjectScreen>:

project_name_text_input: project_name
project_address_text_input: project_address
project_scope_text_input: project_scope

BoxLayout:
    orientation: "vertical"

    Label:
        text: 'Project Name:'
    TextInput:
        id: project_name

    Label:
        text: 'Project Address:'
    TextInput:
        id: project_address

    Label:
        text: 'Project Scope:'
    TextInput:
        id: project_scope

    BoxLayout:
        padding: 15
        spacing: 25
        Button:
            text: 'OK'
            on_press:
                root.add_project_list_item(project_name)
                root.add_project_screen(project_name, project_address, project_scope)
        Button:
            text: 'Back'
            on_press:
                root.manager.transition.direction = 'right'
                root.manager.current = 'home_screen'

<ProjectListScreen>:

project_list: project_list_view

BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Current list of projects'
    Button:
        text: 'Back'
        on_press:
            root.manager.transition.direction = 'right'
            root.manager.current = 'home_screen'

    ListView:
        id: project_list_view
        adapter:
            ListAdapter(data=[], cls=main.ProjectListButton)

<ProjectScreen@Screen>:
    Label:
        text: 'hook up project info here'
    button:
        text: 'Back'

Here are my error messages:

C:\Users\amars\AppData\Local\Programs\Python\Python37-32\python.exe C:/Users/amars/PycharmProjects/ReportingApp/main.py
[INFO   ] [Logger      ] Record log in C:\Users\amars\.kivy\logs\kivy_18-08-30_6.txt
[INFO   ] [Kivy        ] v1.10.1
[INFO   ] [Python      ] v3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[WARNING] [Factory     ] Ignored class "ProjectScreen" re-declaration. Current -  module: None, cls: <class '__main__.ProjectScreen'>, baseclass: None, filename: None. Ignored -  module: None, cls: None, baseclass: Screen, filename: C:\Users\amars\PycharmProjects\ReportingApp\reportingapp.kv.
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.3.0 - Build 20.19.15.4549'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Intel(R) HD Graphics 4400'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 3
[INFO   ] [GL          ] Shading version <b'4.30 - Build 20.19.15.4549'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\listview.py line 845.Called from C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\lang\builder.py line 582 by _apply_rule().
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\simplelistadapter.py line 49.Called from C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\listview.py line 859 by __init__().
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\adapter.py line 111.Called from C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\simplelistadapter.py line 55 by __init__().
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\abstractview.py line 42.Called from C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\listview.py line 865 by __init__().
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\listadapter.py line 185.Called from C:\Users\amars\PycharmProjects\ReportingApp\reportingapp.kv line 85 by <module>().
[WARNING] [Call to deprecated function __init__ in C]\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\adapter.py line 111.Called from C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\adapters\listadapter.py line 186 by __init__().
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "C:/Users/amars/PycharmProjects/ReportingApp/main.py", line 50, in <module>
     ReportingApp().run()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\app.py", line 826, in run
     runTouchApp()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\window_sdl2.py", line 727, in mainloop
     self._mainloop()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\window_sdl2.py", line 460, in _mainloop
     EventLoop.idle()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 340, in idle
     self.dispatch_input()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 325, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 231, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\__init__.py", line 1360, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\__init__.py", line 1376, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\screenmanager.py", line 1191, in on_touch_down
     return super(ScreenManager, self).on_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\relativelayout.py", line 288, in on_touch_down
     ret = super(RelativeLayout, self).on_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\amars\PycharmProjects\ReportingApp\reportingapp.kv", line 61, in <module>
     root.add_project_screen(project_name, project_address, project_scope)
   File "C:/Users/amars/PycharmProjects/ReportingApp/main.py", line 38, in add_project_screen
     s = Factory.ProjectScreen(name=name)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\relativelayout.py", line 265, in __init__
     super(RelativeLayout, self).__init__(**kw)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\floatlayout.py", line 65, in __init__
     super(FloatLayout, self).__init__(**kwargs)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 348, in __init__
     Builder.apply(self, ignored_consts=self._kwargs_applied_init)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\lang\builder.py", line 469, in apply
     self._apply_rule(widget, rule, rule, ignored_consts=ignored_consts)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\lang\builder.py", line 544, in _apply_rule
     cls = Factory_get(cname)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\factory.py", line 130, in __getattr__
     raise AttributeError
 AttributeError

Process finished with exit code 1

As you can see, the app stops at line 38 in the python file, whenever I click the button in the app to call the add_project_screen method. add_project_list_item method seems to work for the listview.

Thank you.

1 Answer 1

0

Problem - AttributeError

The cause of the AttributeError was due to typo error, button: in class rule, <ProjectScreen>:

Solution

Replace button: with Button:

Recommendations

kv file

  1. Replace dynamic class, <ProjectScreen@Screen>: with class rule, <ProjectScreen>:
  2. Instantiate a BoxLayout: widget as children of class rule, <ProjectScreen>: because there are Label and Button widgets, plus preventing widget overlapping.

Snippet

<ProjectScreen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'hook up project info here'
        Button:
            text: 'Back'

Python code

  1. Remove import statement, from kivy.factory import Factory
  2. Remove s = Factory.ProjectScreen(name=name) from add_project_screen() method
  3. Replace self.manager.add_widget(s) with self.manager.add_widget(ProjectScreen(name=name))

Snippet

def add_project_screen(self,project_name_text_input, project_address_text_input, project_scope_text_input):
    name = project_name_text_input.text
    self.manager.add_widget(ProjectScreen(name=name))

Example

main.py

from kivy.app import App    
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.listview import ListItemButton


class ProjectListButton(ListItemButton):
    pass


class HomeScreen(Screen):
    pass


class ProjectListScreen(Screen):
    project_list = ObjectProperty(None)


class ProjectScreen(Screen):
    pass


class NewProjectScreen(Screen):
    project_name_text_input = ObjectProperty(None)
    project_address_text_input = ObjectProperty(None)
    project_scope_text_input = ObjectProperty(None)

    def add_project_list_item(self, project_name_text_input):
        new_project_name = project_name_text_input.text
        project_list_screen = self.manager.get_screen('project_list_screen')
        project_list_screen.project_list.adapter.data.extend([new_project_name])
        # Reset the ListView
        project_list_screen.project_list._trigger_reset_populate()
        #project_name_text_input.text = ''

    def add_project_screen(self,project_name_text_input, project_address_text_input, project_scope_text_input):
        name = project_name_text_input.text
        self.manager.add_widget(ProjectScreen(name=name))


class ReportingApp(App):
    def build(self):
        screen_manager = ScreenManager()
        screen_manager.add_widget(HomeScreen(name="home_screen"))
        screen_manager.add_widget(ProjectListScreen(name="project_list_screen"))
        screen_manager.add_widget(NewProjectScreen(name="new_project_screen"))
        return screen_manager


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

reporting.kv

#:kivy 1.11.0

#:import main main
#:import ListAdapter kivy.adapters.listadapter.ListAdapter
#:import ListItemButton kivy.uix.listview.ListItemButton


<HomeScreen>:
    BoxLayout:
        orientation: "vertical"
        padding: 100
        spacing: 25
        Label:
            size_hint_y: None
            height: 150
            text: "Site Visit Reporting App v1.1"

        Button:
            text: "New Project"
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'new_project_screen'

        Button:
            text: "Project List"
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'project_list_screen'

<NewProjectScreen>:

    project_name_text_input: project_name
    project_address_text_input: project_address
    project_scope_text_input: project_scope

    BoxLayout:
        orientation: "vertical"

        Label:
            text: 'Project Name:'
        TextInput:
            id: project_name

        Label:
            text: 'Project Address:'
        TextInput:
            id: project_address

        Label:
            text: 'Project Scope:'
        TextInput:
            id: project_scope

        BoxLayout:
            padding: 15
            spacing: 25
            Button:
                text: 'OK'
                on_press:
                    root.add_project_list_item(project_name)
                    root.add_project_screen(project_name, project_address, project_scope)
            Button:
                text: 'Back'
                on_press:
                    root.manager.transition.direction = 'right'
                    root.manager.current = 'home_screen'

<ProjectListScreen>:

    project_list: project_list_view

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'Current list of projects'
        Button:
            text: 'Back'
            on_press:
                root.manager.transition.direction = 'right'
                root.manager.current = 'home_screen'

        ListView:
            id: project_list_view
            adapter:
                ListAdapter(data=[], cls=main.ProjectListButton)

<ProjectScreen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'hook up project info here'
        Button:
            text: 'Back'

Output

Img01 - Project abc added Img02 - Project list

Sign up to request clarification or add additional context in comments.

1 Comment

Typo error doh! Thanks for the feedback the app runs smoothly again. Onwards and upwards.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.