Kivy: ошибка атрибута при динамическом добавлении экранного виджета - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь создать экземпляр динамического класса ProjectScreen при вызове add_project_screen. Я хочу создать различные экземпляры ProjectScreen, каждый из которых имеет свое имя, полученное из project_name_text_input. Вот мои файлы .py и .kv:

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()

и вот файл .kv:

#: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'

Вот мои сообщения об ошибках:

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

Как видите, приложение останавливается на строке 38 в файле python, когда я нажимаю кнопку в приложении, чтобы вызвать метод add_project_screen. Метод add_project_list_item, похоже, работает для просмотра списка.

Спасибо.

1 Ответ

0 голосов
/ 30 августа 2018

Проблема - AttributeError

Причиной AttributeError была ошибка опечатки, button: в правиле класса, <ProjectScreen>:

Решение

Заменить button: на Button:

Рекомендации

файл кв

  1. Заменить динамический класс, <ProjectScreen@Screen>: на правило класса, <ProjectScreen>:
  2. Создание BoxLayout: виджета как потомков правила класса, <ProjectScreen>:, потому что есть виджеты Label и Button, плюс предотвращение наложения виджетов.

Отрывок

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

код Python

  1. Удалить оператор импорта, from kivy.factory import Factory
  2. Удалить s = Factory.ProjectScreen(name=name) из add_project_screen() метод
  3. Заменить self.manager.add_widget(s) на self.manager.add_widget(ProjectScreen(name=name))

Отрывок

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))

Пример * +1049 * 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' выход

Img01 - Project abc added Img02 - Project list

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...