Как переключиться на динамически создаваемый экран из объекта RecycleView SelectableButton? - PullRequest
0 голосов
/ 30 сентября 2018

У меня есть приложение, в котором я могу динамически создавать виджет экрана и объект viewclass кнопки повторного просмотра из одного и того же текстового виджета.Имя динамически создаваемого виджета ProjectScreen совпадает со значением, содержащимся в dict для SelectableButton.

Мне трудно переключиться на виджет ProjectScreen после нажатия на объект ViewClass представления повторного просмотра SelectableButton с тем женазвание.Примеры кода ниже:

from kivy.app import App

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, BooleanProperty

'''Library imports for recycleview'''
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview import RecycleViewBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.behaviors import FocusBehavior


class HomeScreen(Screen):
    pass

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


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = []


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                             RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableButton(RecycleDataViewBehavior, Button):
    """ Add selection support to the Label """
    index = 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):
        name = project_name_text_input.text
        project_list_screen = self.manager.get_screen('project_list_screen')
        project_list_screen.rv.data.insert(0, {'value': 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))
        project_name_text_input.text = ''


screen_manager = ScreenManager()
class ReportingApp(App):
    def build(self):
        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 RecycleView kivy.uix.recycleview.RecycleView
#:import RecycleViewBehavior kivy.uix.recycleview.RecycleView
#:import RecycleDataViewBehavior kivy.uix.recycleview.views.RecycleDataViewBehavior
#:import RecycleBoxLayout kivy.uix.recycleboxlayout.RecycleBoxLayout
#:import LayoutSelectionBehavior kivy.uix.recycleview.layout.LayoutSelectionBehavior
#:import FocusBehavior kivy.uix.behaviors.FocusBehavior


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


<SelectableButton>:
    canvas.before:
        Color:
            rgba: 0.5, 0.5, 0.5, 1
        Rectangle:
            size: self.size
            pos: self.pos
    value: ''
    text: root.value
    on_press:
        root.manager.current = root.value


<ProjectListScreen>:

    rv: rv

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

        RV:
            id: rv
            scroll_type: ['bars', 'content']
            scroll_wheel_distance: dp(114)
            bar_width: dp(10)
            viewclass: 'SelectableButton'
            SelectableRecycleBoxLayout:
                default_size: None, dp(56)
                default_size_hint: 1, None
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'
                spacing: dp(2)
                multiselect: False
                touch_multiselect: False

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

Я получаю следующую ошибку, когда нажимаю объект SelectableButton в повторном просмотре:

[INFO   ] [Logger      ] Record log in C:\Users\amars\.kivy\logs\kivy_18-09-29_32.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
[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
[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 69, 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 1364, in on_motion
     self.dispatch('on_touch_up', 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 1400, in on_touch_up
     if w.dispatch('on_touch_up', 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 1201, in on_touch_up
     return super(ScreenManager, self).on_touch_up(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 482, in on_touch_up
     if child.dispatch('on_touch_up', 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 304, in on_touch_up
     ret = super(RelativeLayout, self).on_touch_up(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 482, in on_touch_up
     if child.dispatch('on_touch_up', 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 482, in on_touch_up
     if child.dispatch('on_touch_up', 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\scrollview.py", line 848, in on_touch_up
     if self.dispatch('on_scroll_stop', 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\scrollview.py", line 887, in on_scroll_stop
     self.simulate_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\scrollview.py", line 607, in simulate_touch_down
     ret = super(ScrollView, 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\behaviors\focus.py", line 443, in on_touch_down
     return super(FocusBehavior, 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\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 82, in <module>
     root.manager.current = root.value
   File "kivy\weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'SelectableButton' object has no attribute 'manager'

Каким-то образом мне нужно, чтобы виджет SelectableButton «знал» менеджер экрана, чтобы я мог переключиться на нужный экран.

Насколько я понимаю, вызов root.manager будет идти непосредственно к моему корневому виджету, которыйвиджет менеджера экранаРазве SelectableButton не является дочерним виджетом RV, который является дочерним виджетом ProjectListScreen?И, следовательно, все еще дочерний виджет под корневым виджетом ScreenManager?

Любая помощь приветствуется.Спасибо.

1 Ответ

0 голосов
/ 30 сентября 2018

Возможное решение - передать информацию в data в RecycleView, для этого мы должны создать свойство в SelectableButton:

*. Py

def add_project_list_item(self,project_name_text_input):
    name = project_name_text_input.text
    project_list_screen = self.manager.get_screen('project_list_screen')
    project_list_screen.rv.data.insert(0, {'value': name, 'manager': self.manager}) # <---

*. Кв

<SelectableButton>:
    manager: None # <---
    canvas.before:
        Color:
            rgba: 0.5, 0.5, 0.5, 1
        Rectangle:
            size: self.size
            pos: self.pos
    value: ''
    text: root.value
    on_press:
        root.manager.current = root.value # <---
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...